Mongo按数组中的匹配数排序

时间:2017-05-25 14:04:08

标签: mongodb mongodb-query aggregation-framework

让我说我的测试数据是

db.multiArr.insert({"ID" : "fruit1","Keys" : ["apple", "orange", "banana"]})
db.multiArr.insert({"ID" : "fruit2","Keys" : ["apple", "carrot", "banana"]})

获得像胡萝卜一样的个人水果

db.multiArr.find({'Keys':{$in:['carrot']}})

当我对橙色和香蕉进行查询或查询时,我会看到记录fruit1然后是fruit2

db.multiArr.find({ $or: [{'Keys':{$in:['carrot']}}, {'Keys':{$in:['banana']}}]})

输出的结果应该是fruit2然后是fruit1,因为fruit2有胡萝卜和香蕉

1 个答案:

答案 0 :(得分:5)

要先实际回答这个问题,你需要"计算"给定条件的匹配数,以便排序"排序"结果以优先选择返回顶部的大多数匹配。

为此,您需要聚合框架,这是您用于"计算"和"操纵" MongoDB中的数据:

db.multiArr.aggregate([
  { "$match": { "Keys": { "$in": [ "carrot", "banana" ] } } },
  { "$project": {
    "ID": 1,
    "Keys": 1,
    "order": {
      "$size": {
        "$setIntersection": [ ["carrot", "banana"], "$Keys" ]
      }
    }
  }},
  { "$sort": { "order": -1 } }
])

在版本低于3的MongoDB上,您可以使用更长的格式:

db.multiArr.aggregate([
  { "$match": { "Keys": { "$in": [ "carrot", "banana" ] } } },
  { "$unwind": "$Keys" },
  { "$group": {
    "_id": "$_id",
    "ID": { "$first": "$ID" },
    "Keys": { "$push": "$Keys" },
    "order": {
      "$sum": {
        { "$cond": [
          { "$or": [
           { "$eq": [ "$Keys", "carrot" ] },
           { "$eq": [ "$Keys", "banana" ] }
         ]},
         1,
         0
        ]}
      }
    }
  }},
  { "$sort": { "order": -1 } }
])

在任何一种情况下,此处的功能是首先通过提供"列表"将可能的文档与条件匹配。与$in的争论。一旦获得结果,您希望"计算"数组中匹配元素的数量为" list"提供的可能值。

在现代形式中,$setIntersection运算符比较两个"列表"返回一个只包含" unique"的新数组。匹配成员。由于我们想知道有多少匹配,我们只需返回该列表的$size

在旧版本中,您将文档数组与$unwind分开,以便对其执行操作,因为旧版本缺少使用数组而无需更改的较新运算符。然后,该流程会单独查看每个值,如果$or中的任一表达式与可能的值匹配,则$cond三元组会将1的值返回到$sum累加器,否则{ {1}}。最终结果是相同的"匹配数"如现代版本所示。

最后一件事就是$sort结果基于"匹配数"返回的是最匹配的是" top"。这是"降序"因此,您提供0来表示。

关于$ in和数组

的附录

你误解了关于初学者的MongoDB查询的一些事情。 -1运算符实际上是用于"列表"像这样的论点:

$in

这实际上是简单的说法"匹配胡萝卜' ' banana'在物业' Keys'" 。甚至可以用这样的长篇形式写出来:

{ "Keys": { "$in": [ "carrot", "banana" ] } }

如果它是一个"单数"那真的应该引导你。匹配条件,然后您只需提供与属性匹配的值:

{ "$or": [{ "Keys": "carrot" }, { "Keys": "banana" }] }

这应该涵盖您使用$in来匹配文档中数组的属性的误解。相反,"反向" case是预期的用法,而你提供一个"参数列表"匹配给定的属性,该属性是数组或只是一个值。

MongoDB查询引擎在相等或类似操作中不区分单个值或值数组。