如何权衡文档以创建排序标准?

时间:2014-02-18 17:31:27

标签: javascript mongodb mongodb-query aggregation-framework

我正在尝试聚合一个集合,其中有一些文档看起来像这样:

[
  {  
    "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运算符不是布尔值,所以它不起作用。我环顾四周,找不到任何可以帮助我的操作员。

1 个答案:

答案 0 :(得分:1)

正如您所说,您需要一个逻辑运算符来评估$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 ]}
        }
    }}
])

我将把剩下的实现留给你,但这应该显示你想要做的匹配点的基本结构。

加成

根据您的评论,似乎还有一个您正在努力解决的编程问题,与您如何执行这样的聚合相关,您可以使用上面提供的表单中的数组项进行查询:

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 ]}
        }
    }}
])

或者就此而言,您需要构建的任何部分。这通常是在现实世界中如何完成的,我们几乎从不硬编码像这样的数据结构。