我遇到了使用MongoDB进行高级计数查询的问题。
我想在文档字段中计算 内的对象,但前提是存在与查询匹配的前一个元素且 较旧数组中的em> 。
让我解释....
我有一个容器文档,看起来像:
{
"_id" : ...,
[...]
"objects" : [ ]
}
在对象字段内:
我有对象文档看起来像:
[
{
"_id" : ...,
"name" : "foo",
"properties" = [ ],
"time" = 000000042
}
{
"_id" : ...,
"name" : "bar",
"properties" = [ ],
"time" = 000000424
}
{
"_id" : ...,
"name" : "baz",
"properties" = [ ],
"time" = 000004242
}
现在我算一下容器文件包含多少:
具有对象1(foo),
的容器的 计数
带有对象1和2(foo和bar)的容器的 计数 ,
对象1,2和3(foo,bar,baz)的容器的 计数
但是现在我想只计算 bar 旧 foo (使用时间字段)时才计算foo和bar ... <登记/>
具有对象1(foo),
的容器的 计数
具有对象1和2(foo和bar)的容器的 计数 , AND foo.time&lt; bar.time
具有对象1,2和3的容器的 count (foo,bar,baz) AND foo.time&lt; bar.time&lt; baz.time
问题是需要为每个容器更改时间字段。 换句话说:我如何使用每个文档的动态查询
这里是代码示例:
foreach ($COUNTER[ARRAY_FIELDS_NAME_TO_COUNT] as $key => $value)
{
// Build the query (Name & properties)
$match[$key] = array('$elemMatch' => array('name' => $value['name']));
foreach ($value['properties'] as $propertyName => $propertyValue)
$match[$key]['$elemMatch']["properties.$propertyName"] = $propertyValue;
// Time checking
if ($key > 0)
{
//FIXME with a... dynamics query searching inside current doc??
// or a special var set to the previous object matched... or MapReduce..
}
// Make the query
$query = array('objects' => array('$all' => $match));
$result[$key]['count'] = $db->person->count($query);
}
我是MongoDB的新手,我真的不知道有效实现这一目标的最佳做法是什么!
问候!
答案 0 :(得分:1)
以下是在shell(javascript)中使用Aggregation Framework执行此操作的方法。
请注意,为了便于阅读,我将其拆分为多行,实际查询是最后一行。我曾经使用过foo bar和baz但当然你想调整到更合适的东西。
match = { "$match" : { "objects.name" : "foo" } };
unwind = { "$unwind" : "$objects" };
projectDates = {"$project" : {
"_id" : 1,
"objects" : 1,
"fooDate" : {
"$cond" : [
{
"$eq" : [
"$objects.name",
"foo"
]
},
"$objects.time",
0
]
},
"barDate" : {
"$cond" : [
{
"$eq" : [
"$objects.name",
"bar"
]
},
"$objects.time",
0
]
},
"bazDate" : {
"$cond" : [
{
"$eq" : [
"$objects.name",
"baz"
]
},
"$objects.time",
0
]
}
}
};
group = {"$group" : {
"_id" : "$_id",
"objects" : {
"$push" : "$objects"
},
"maxFooDate" : {
"$max" : "$fooDate"
},
"maxBarDate" : {
"$max" : "$barDate"
},
"maxBazDate" : {
"$max" : "$bazDate"
}
}
};
projectCount = {"$project" : {
"_id" : 1,
"foos" : {
"$add" : [
1,
0
]
},
"foosAndBars" : {
"$cond" : [
{
"$lt" : [
"$maxFooDate",
"$maxBarDate"
]
},
1,
0
]
},
"foosBarsAndBazs" : {
"$cond" : [
{
"$and" : [
{
"$lt" : [
"$maxBarDate",
"$maxBazDate"
]
},
{
"$lt" : [
"$maxFooDate",
"$maxBarDate"
]
}
]
},
1,
0
]
}
}
};
countFoos = {"$group" : {
"_id" : "FoosBarsBazs",
"Foos" : {
"$sum" : "$foos"
},
"FBs" : {
"$sum" : "$foosAndBars"
},
"FBBs" : {
"$sum" : "$foosBarsAndBazs"
}
}
};
db.collection.aggregate([match, unwind, projectDates, projectCount, countFoos]).result