在MongoDB中搜索数组并按匹配数排序

时间:2012-09-13 12:04:35

标签: mongodb aggregation-framework nosql

问题是下一个问题:

Get documents with tags in list, ordered by total number of matches

但是他们说使用聚合框架是可能的,这是可能的吗?

2 个答案:

答案 0 :(得分:6)

是的,可以使用聚合框架。

<强>假设

查询

这种方法会强制您展开结果并使用未展开的结果重新评估匹配谓词,因此效率非常低。

db.test_col.aggregate(
    {$match: {tags: {$in: ["shirt","cotton","black"]}}}, 
    {$unwind: "$tags"}, 
    {$match: {tags: {$in: ["shirt","cotton","black"]}}}, 
    {$group: {
        _id:{"_id":1}, 
        matches:{$sum:1}
    }}, 
    {$sort:{matches:-1}}
);

预期结果

{
    "result" : [
        {
            "_id" : {
                "_id" : ObjectId("5051f1786a64bd2c54918b26")
            },
            "matches" : 3
        },
        {
            "_id" : {
                "_id" : ObjectId("5051f1726a64bd2c54918b24")
            },
            "matches" : 2
        },
        {
            "_id" : {
                "_id" : ObjectId("5051f1756a64bd2c54918b25")
            },
            "matches" : 1
        }
    ],
    "ok" : 1
}

答案 1 :(得分:0)

使用 $ size $ setIntersection 可以有效解决此问题,而不会引起内存倍增。

tagList = ['shirt', 'cotton', 'black']

db.test_col.aggregate(
    {$match: {tags: {$in: ["shirt","cotton","black"]}}}, 
    {$project: 
        {"title":1,"tags":1}, 
        {$order: 
            {"$size": 
                {"$setIntersection": [ tagList, "$tags" ]}}, 
    {$sort:{order:-1}}
    );
  1. 首先,我们匹配至少具有一个元素匹配的文档。

  2. 然后,我们投影所需的键/列以及新的订单键/列。通过获取“ db中的标签”和“查询中的标签”之间相交元素的数量来生成顺序。

  3. 然后我们以降序进行简单排序。 这对我有用。 回答了here

    的类似问题