英文:
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 ISODate
s 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
IBsonSerializer
class to convert fromDateTime
type tolong
type.
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
BsonSerializer
attribute withDateToLongConverter
toDate
property.
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
Model
class.
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论