Mongodb 查找文档时显示子文档中的最新值
鉴于以下文件结构:Mongodb 查找文档时显示子文档中的最新值,mongodb,Mongodb,鉴于以下文件结构: { _id: "abc123", name: "Some name", properties: [ { definition: "temp", values: [ { created: 1376061128, value: 82 }, { created: 1376062368, value: 85
{
_id: "abc123",
name: "Some name",
properties: [
{
definition: "temp",
values: [
{
created: 1376061128,
value: 82
},
{
created: 1376062368,
value: 85
},
{
created: 1376062627,
value: 88
}
]
},
{
definition: "alert",
values: [
{
created: 1376061128,
value: 0
},
{
created: 1376062368,
value: 1
},
{
created: 1376062627,
value: 0
}
]
}
]
}
我希望能够返回仅包含每个属性的“最新”(基于创建的)值的文档,如下所示:
{
_id: "abc123",
name: "Some name",
properties: [
{
definition: "temp",
values: [
created: 1376062627,
value: 88
]
},
{
definition: "alert",
values: [
created: 1376062627,
value: 0
]
}
]
}
一般来说,我对处理MongoDB和map/reduce还比较陌生,所以我不确定应该朝哪个方向看。这是一个新的数据模型,因此如果有关于修改文档模型的建议,我也愿意听取。如果值只是按时间顺序(如数据所示)推送到数组中,您可以使用:
db.coll.find({},{“properties.values”){$slice:-1}
它不能保证最新的。它将返回数组中的最后一项。由于您的值数组是按创建的隐式排序的,因此这将起作用
由于聚合框架不允许您展开嵌套数组,如果不是这种情况(创建时没有推送值),您将不得不使用map reduce。如果值只是按时间顺序推送到数组(如数据所示),您可以使用:
db.coll.find({},{“properties.values”){$slice:-1})
它不能保证最新的。它将返回数组中的最后一项。由于您的值数组是按创建的隐式排序的,因此这将起作用
由于聚合框架不允许您展开嵌套数组,如果不是这种情况(创建时不会推送值),我认为您将不得不使用map reduce。在聚合管道中,您可以使用and运算符,这对您的情况很有帮助。为此,我花了一段时间构建了一个聚合管道,它可能不是最优的,但它正在工作:
db.test.aggregate([
{$unwind : "$properties"},
{$unwind : "$properties.values"},
{$sort : {
"_id" : 1,
"name" : 1,
"properties.definition" : 1,
"properties.values.created" : 1
}},
{$group : {
"_id" : {
"_id" : "$_id",
"name" : "$name",
"definition" : "$properties.definition"
},
"created" : {$last : "$properties.values.created"},
"value" : {$last : "$properties.values.value"}
}}
])
结果是:
{
"result" : [
{
"_id" : {
"_id" : "abc123",
"name" : "Some name",
"definition" : "temp"
},
"created" : 1376062627,
"value" : 88
},
{
"_id" : {
"_id" : "abc123",
"name" : "Some name",
"definition" : "alert"
},
"created" : 1376062627,
"value" : 0
}
],
"ok" : 1
}
您可能需要对结果进行一些转换,但是,对吗?在聚合管道中,您可以使用and运算符,这对您的案例很有帮助。为此,我花了一段时间构建了一个聚合管道,它可能不是最优的,但它正在工作:
db.test.aggregate([
{$unwind : "$properties"},
{$unwind : "$properties.values"},
{$sort : {
"_id" : 1,
"name" : 1,
"properties.definition" : 1,
"properties.values.created" : 1
}},
{$group : {
"_id" : {
"_id" : "$_id",
"name" : "$name",
"definition" : "$properties.definition"
},
"created" : {$last : "$properties.values.created"},
"value" : {$last : "$properties.values.value"}
}}
])
结果是:
{
"result" : [
{
"_id" : {
"_id" : "abc123",
"name" : "Some name",
"definition" : "temp"
},
"created" : 1376062627,
"value" : 88
},
{
"_id" : {
"_id" : "abc123",
"name" : "Some name",
"definition" : "alert"
},
"created" : 1376062627,
"value" : 0
}
],
"ok" : 1
}
您可能需要对结果进行一些转换,但是,对吗?这可能会起作用,但是查询速度会很慢,对于这样一个简单的要求来说似乎太多了。我不是说它是完美的。如果OP 100%确定属性是按时间排序的,那么
$slice
可能会按照@orid工作。这是更通用的,因此+1这可能会工作,但查询速度会很慢,对于这样一个简单的要求来说似乎太多了。我不是说它是完美的。如果OP 100%确定属性是按时间排序的,则$slice
可能按照@orid工作。这更通用,因此+1在这种情况下,值始终基于时间,因此这是完美的。我把它复杂化了。谢谢在这种情况下,值总是基于时间的,因此这是完美的。我把它复杂化了。谢谢