使用 `$toLong` 在 MongoDB C# 查询中

huangapple go评论111阅读模式
英文:

Using `$toLong` in MongoDB C# Queries

问题

我正在努力将下面的Mongo聚合管道转换为其C#等效项。我试图使用内置的$toLongISODate转换为Unix时间戳。可能有数百万个文档,因此不可行的是使用.ToList().Select(x => ConvertToTimestamp(x.date))

假设我有以下文档:

  1. [
  2. {
  3. "value": 100,
  4. "date": ISODate("2022-03-26T04:38:28.044Z")
  5. },
  6. {
  7. "value": 50,
  8. "date": ISODate("2022-03-26T04:38:28.044Z")
  9. },
  10. {
  11. "value": 23,
  12. "date": ISODate("2022-03-26T04:38:28.044Z")
  13. },
  14. {
  15. "value": 199,
  16. "date": ISODate("2022-03-26T04:38:28.044Z")
  17. }
  18. ]

我有以下工作的聚合查询:

  1. db.collection.aggregate({
  2. $project: {
  3. date: {
  4. $toLong: "$date"
  5. },
  6. value: 1,
  7. }
  8. })

我得到了预期的输出:

  1. [
  2. {
  3. "_id": ObjectId("5a934e000102030405000000"),
  4. "date": NumberLong(1648269508044),
  5. "value": 100
  6. },
  7. {
  8. "_id": ObjectId("5a934e000102030405000001"),
  9. "date": NumberLong(1648269508044),
  10. "value": 50
  11. },
  12. {
  13. "_id": ObjectId("5a934e000102030405000002"),
  14. "date": NumberLong(1648269508044),
  15. "value": 23
  16. },
  17. {
  18. "_id": ObjectId("5a934e000102030405000003"),
  19. "date": NumberLong(1648269508044),
  20. "value": 199
  21. }
  22. ]

现在,问题是如何使用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:

  1. [
  2. {
  3. "value": 100,
  4. "date": ISODate("2022-03-26T04:38:28.044Z")
  5. },
  6. {
  7. "value": 50,
  8. "date": ISODate("2022-03-26T04:38:28.044Z")
  9. },
  10. {
  11. "value": 23,
  12. "date": ISODate("2022-03-26T04:38:28.044Z")
  13. },
  14. {
  15. "value": 199,
  16. "date": ISODate("2022-03-26T04:38:28.044Z")
  17. }
  18. ]

I have the following aggregation query that works

  1. db.collection.aggregate({
  2. $project: {
  3. date: {
  4. $toLong: "$date"
  5. },
  6. value: 1,
  7. }
  8. })

And I get the expected output

  1. [
  2. {
  3. "_id": ObjectId("5a934e000102030405000000"),
  4. "date": NumberLong(1648269508044),
  5. "value": 100
  6. },
  7. {
  8. "_id": ObjectId("5a934e000102030405000001"),
  9. "date": NumberLong(1648269508044),
  10. "value": 50
  11. },
  12. {
  13. "_id": ObjectId("5a934e000102030405000002"),
  14. "date": NumberLong(1648269508044),
  15. "value": 23
  16. },
  17. {
  18. "_id": ObjectId("5a934e000102030405000003"),
  19. "date": NumberLong(1648269508044),
  20. "value": 199
  21. }
  22. ]

Now, the question is, how to do this with the fluent aggregation API in C#?

答案1

得分: 0

方法1: 将聚合查询作为BsonDocument传递。

  1. var pipelineDefinition = new BsonDocument[]
  2. {
  3. new BsonDocument
  4. {
  5. {
  6. "$project", new BsonDocument
  7. {
  8. { "date", new BsonDocument { { "$toLong", "$date" } } },
  9. { "value", 1 }
  10. }
  11. }
  12. }
  13. };
  14. List<Model> result = _collection.Aggregate<Model>(pipelineDefinition)
  15. .ToList();

方法2: 使用BsonSerializer

  1. 实现IBsonSerializer类以将DateTime类型转换为long类型。
  1. public class DateToLongConverter : IBsonSerializer<long>
  2. {
  3. public Type ValueType => typeof(long);
  4. public long Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
  5. {
  6. var bsonReader = context.Reader;
  7. return bsonReader.ReadDateTime();
  8. }
  9. public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, long value)
  10. {
  11. var bsonWriter = context.Writer;
  12. bsonWriter.WriteInt64(value);
  13. }
  14. public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
  15. {
  16. var bsonWriter = context.Writer;
  17. bsonWriter.WriteInt64((long)value);
  18. }
  19. object IBsonSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
  20. {
  21. var bsonReader = context.Reader;
  22. return bsonReader.ReadDateTime();
  23. }
  24. }
  1. Date属性上应用BsonSerializer属性,使用DateToLongConverter
  1. public class Model
  2. {
  3. public ObjectId Id { get; set; }
  4. [BsonSerializer(typeof(DateToLongConverter))]
  5. public long Date { get; set; }
  6. public int Value { get; set; }
  7. }
  1. Model类注册类映射。
  1. BsonClassMap.RegisterClassMap<Model>(cm =>
  2. {
  3. cm.AutoMap();
  4. cm.MapMember(x => x.Date)
  5. .SetSerializer(new DateToLongConverter());
  6. });
  1. 查询数据:
  1. List<Model> result = (await _collection.FindAsync(new BsonDocument()))
  2. .ToList();

演示

使用 `$toLong` 在 MongoDB C# 查询中

英文:

Approach 1: Pass aggregation query as BsonDocument.

  1. var pipelineDefinition = new BsonDocument[]
  2. {
  3. new BsonDocument
  4. {
  5. {
  6. &quot;$project&quot;, new BsonDocument
  7. {
  8. { &quot;date&quot;, new BsonDocument { { &quot;$toLong&quot;, &quot;$date&quot; } } },
  9. { &quot;value&quot;, 1 }
  10. }
  11. }
  12. }
  13. };
  14. List&lt;Model&gt; result = _collection.Aggregate&lt;Model&gt;(pipelineDefinition)
  15. .ToList();

Approach 2: Work with BsonSerializer.

  1. Implement IBsonSerializer class to convert from DateTime type to long type.
  1. public class DateToLongConverter : IBsonSerializer&lt;long&gt;
  2. {
  3. public Type ValueType =&gt; typeof(long);
  4. public long Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
  5. {
  6. var bsonReader = context.Reader;
  7. return bsonReader.ReadDateTime();
  8. }
  9. public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, long value)
  10. {
  11. var bsonWriter = context.Writer;
  12. bsonWriter.WriteInt64(value);
  13. }
  14. public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
  15. {
  16. var bsonWriter = context.Writer;
  17. bsonWriter.WriteInt64((long)value);
  18. }
  19. object IBsonSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
  20. {
  21. var bsonReader = context.Reader;
  22. return bsonReader.ReadDateTime();
  23. }
  24. }
  1. Apply BsonSerializer attribute with DateToLongConverter to Date property.
  1. public class Model
  2. {
  3. public ObjectId Id { get; set; }
  4. [BsonSerializer(typeof(DateToLongConverter))]
  5. public long Date { get; set; }
  6. public int Value { get; set; }
  7. }
  1. Register class map for Model class.
  1. BsonClassMap.RegisterClassMap&lt;Model&gt;(cm =&gt;
  2. {
  3. cm.AutoMap();
  4. cm.MapMember(x =&gt; x.Date)
  5. .SetSerializer(new DateToLongConverter());
  6. });
  1. To query data:
  1. List&lt;Model&gt; result = (await _collection.FindAsync(new BsonDocument()))
  2. .ToList();

> Demo

使用 `$toLong` 在 MongoDB C# 查询中

huangapple
  • 本文由 发表于 2023年3月7日 15:30:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/75659073.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定