我正在尝试聚合一个集合,其中有如下文档:
[
{
"title" : 1984,
"tags" : ['dystopia', apocalypse', 'future',....]
},
....
]
我有一个关键字的标准数组,例如:
var keywords = ['future', 'google', 'cat',....]
我想实现的是聚合集合,以便根据"方便"标准对其进行$分组,以便根据标记字段中包含更多关键字的文档对文档进行排序。
这意味着,如果一个文档的标签中包含:"future"、"google"、"cat",则它将被排序在另一个包含"future"、"cat"、"apple"的文档之前。
到目前为止,我已经尝试过这样的东西:
db.books.aggregate(
{ $group : { _id : {title:"$title"} , convenience: { $sum: { $cond: [ {tags: {$in: keywords}}, 1, 0 ] } } } },
{ $sort : {'convenience': -1}})
但是$in
运算符不是布尔运算符,因此它不起作用。我环顾四周,没有找到任何能帮我的接线员。
正如您所说,您需要一个逻辑运算符来计算$cond。它有点简洁,但这里有一个使用$or的实现:
db.books.aggregate([
{$unwind: "$tags" },
{$group: {
_id: "$title",
weight: {
$sum: {$cond: [
// Test *equality* of the `tags` value against any of the list
{$or: [
{$eq: ["$tags", "future"]},
{$eq: ["$tags", "google"]},
{$eq: ["$tags", "cat"]},
]},
1, 0 ]}
}
}}
])
我将把其余的实现留给您,但这应该显示出您想要进行匹配的基本构造
添加
从您的评论来看,似乎还有一个您正在努力解决的编程问题,与您如何执行这样的聚合有关,其中您有一个Array项目以上面给出的形式进行查询:
var keywords = ['future', 'google', 'cat',....]
由于此结构不能直接用于管道条件,因此需要将其转换为所需内容。每种语言都有自己的方法,但在JavaScript版本中:
var keywords = ['future', 'google', 'cat'];
var orCondition = [];
keywords.forEach(function(value) {
var doc = {$eq: [ "$tags", value ]};
orCondition.push(doc);
});
然后只需使用orCondition
变量定义聚合查询:
db.books.aggregate([
{$unwind: "$tags" },
{$group: {
_id: "$title",
weight: {
$sum: {$cond: [
{$or: orCondition }
1, 0 ]}
}
}}
])
或者就这一点而言,你需要构建的任何部分。在现实世界中,我们通常是这样做的,在那里我们几乎永远不会硬编码这样的数据结构。