英文:
Using `$toLong` in MongoDB C# Queries
问题
我正在努力将下面的Mongo聚合管道转换为其C#等效项。我试图使用内置的$toLong将ISODate转换为Unix时间戳。可能有数百万个文档,因此不可行的是使用.ToList().Select(x => ConvertToTimestamp(x.date))。
假设我有以下文档:
[
  {
    "value": 100,
    "date": ISODate("2022-03-26T04:38:28.044Z")
  },
  {
    "value": 50,
    "date": ISODate("2022-03-26T04:38:28.044Z")
  },
  {
    "value": 23,
    "date": ISODate("2022-03-26T04:38:28.044Z")
  },
  {
    "value": 199,
    "date": ISODate("2022-03-26T04:38:28.044Z")
  }
]
我有以下工作的聚合查询:
db.collection.aggregate({
  $project: {
    date: {
      $toLong: "$date"
    },
    value: 1,
  }
})
我得到了预期的输出:
[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "date": NumberLong(1648269508044),
    "value": 100
  },
  {
    "_id": ObjectId("5a934e000102030405000001"),
    "date": NumberLong(1648269508044),
    "value": 50
  },
  {
    "_id": ObjectId("5a934e000102030405000002"),
    "date": NumberLong(1648269508044),
    "value": 23
  },
  {
    "_id": ObjectId("5a934e000102030405000003"),
    "date": NumberLong(1648269508044),
    "value": 199
  }
]
现在,问题是如何使用C#中的流畅聚合API来执行此操作?
英文:
I'm struggling to convert the below Mongo aggregation pipeline into its C# equivalent. I am trying to convert ISODates to unix timestamps using the built in $toLong. There could be millions of documents, so doing .ToList().Select(x => ConvertToTimestamp(x.date)) is not feasible.
Say I have the following documents:
[
  {
    "value": 100,
    "date": ISODate("2022-03-26T04:38:28.044Z")
  },
  {
    "value": 50,
    "date": ISODate("2022-03-26T04:38:28.044Z")
  },
  {
    "value": 23,
    "date": ISODate("2022-03-26T04:38:28.044Z")
  },
  {
    "value": 199,
    "date": ISODate("2022-03-26T04:38:28.044Z")
  }
]
I have the following aggregation query that works
db.collection.aggregate({
  $project: {
    date: {
      $toLong: "$date"
    },
    value: 1,
  }
})
And I get the expected output
[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "date": NumberLong(1648269508044),
    "value": 100
  },
  {
    "_id": ObjectId("5a934e000102030405000001"),
    "date": NumberLong(1648269508044),
    "value": 50
  },
  {
    "_id": ObjectId("5a934e000102030405000002"),
    "date": NumberLong(1648269508044),
    "value": 23
  },
  {
    "_id": ObjectId("5a934e000102030405000003"),
    "date": NumberLong(1648269508044),
    "value": 199
  }
]
Now, the question is, how to do this with the fluent aggregation API in C#?
答案1
得分: 0
方法1: 将聚合查询作为BsonDocument传递。
var pipelineDefinition = new BsonDocument[]
{
    new BsonDocument
    {
        {
            "$project", new BsonDocument
            {
                { "date", new BsonDocument { { "$toLong", "$date" } } },
                { "value", 1 }
            }
        }
    }
};
List<Model> result = _collection.Aggregate<Model>(pipelineDefinition)
    .ToList();
方法2: 使用BsonSerializer。
- 实现
IBsonSerializer类以将DateTime类型转换为long类型。 
public class DateToLongConverter : IBsonSerializer<long>
{
    public Type ValueType => typeof(long);
    public long Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        var bsonReader = context.Reader;
        return bsonReader.ReadDateTime();
    }
    public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, long value)
    {
        var bsonWriter = context.Writer;
        bsonWriter.WriteInt64(value);
    }
    public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
    {
        var bsonWriter = context.Writer;
        bsonWriter.WriteInt64((long)value);
    }
    object IBsonSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        var bsonReader = context.Reader;
        return bsonReader.ReadDateTime();
    }
}
- 在
Date属性上应用BsonSerializer属性,使用DateToLongConverter。 
public class Model
{
    public ObjectId Id { get; set; }
    [BsonSerializer(typeof(DateToLongConverter))]
    public long Date { get; set; }
    public int Value { get; set; }
}
- 为
Model类注册类映射。 
BsonClassMap.RegisterClassMap<Model>(cm =>
{
    cm.AutoMap();
    cm.MapMember(x => x.Date)
        .SetSerializer(new DateToLongConverter());
});
- 查询数据:
 
List<Model> result = (await _collection.FindAsync(new BsonDocument()))
    .ToList();
演示

英文:
Approach 1: Pass aggregation query as BsonDocument.
var pipelineDefinition = new BsonDocument[]
{
    new BsonDocument
    {
        {
            "$project", new BsonDocument
            {
                { "date", new BsonDocument { { "$toLong", "$date" } } },
                { "value", 1 }
            }
        }
    }
};
List<Model> result = _collection.Aggregate<Model>(pipelineDefinition)
    .ToList();
Approach 2: Work with BsonSerializer.
- Implement 
IBsonSerializerclass to convert fromDateTimetype tolongtype. 
public class DateToLongConverter : IBsonSerializer<long>
{
    public Type ValueType => typeof(long);
    public long Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        var bsonReader = context.Reader;
        return bsonReader.ReadDateTime();
    }
    public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, long value)
    {
        var bsonWriter = context.Writer;
        bsonWriter.WriteInt64(value);
    }
    public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
    {
        var bsonWriter = context.Writer;
        bsonWriter.WriteInt64((long)value);
    }
    object IBsonSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        var bsonReader = context.Reader;
        return bsonReader.ReadDateTime();
    }
}
- Apply 
BsonSerializerattribute withDateToLongConvertertoDateproperty. 
public class Model
{
    public ObjectId Id { get; set; }
    [BsonSerializer(typeof(DateToLongConverter))]
    public long Date { get; set; }
    public int Value { get; set; }
}
- Register class map for 
Modelclass. 
BsonClassMap.RegisterClassMap<Model>(cm =>
{
    cm.AutoMap();
    cm.MapMember(x => x.Date)
        .SetSerializer(new DateToLongConverter());
});
- To query data:
 
List<Model> result = (await _collection.FindAsync(new BsonDocument()))
    .ToList();
> Demo
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论