如何在MongoDb中为搜索的文档分配权重?

Gau*_*pta 1 mongodb mongodb-query aggregation-framework

对于您来说,这听起来像是一个简单的问题,但我花了3个多小时才能实现,但是我陷入了困境。

输入

  1. 关键字清单
  2. 标签清单

问题陈述:我需要从数据库中找到满足以下条件的所有文档:

  1. 列出具有1个或多个匹配关键字的文档。(已实现)
  2. 列出具有1个或多个匹配标签的文档。(已实现)
  3. 根据权重对找到的文档进行排序:每个匹配的关键字携带2分,每个匹配的标签携带1分。

查询:如何达到要求#3。

我的尝试:在我的尝试中,我只能根据关键字match列出(也不要将weight乘以2)。

标签是文档的数组。每个标签的结构就像

{
   "id" : "ICC",
   "some Other Key" : "some Other value"
}
Run Code Online (Sandbox Code Playgroud)

关键字是字符串数组:

["women", "cricket"]
Run Code Online (Sandbox Code Playgroud)

查询:

var predicate = [
    {
        "$match": {
            "$or": [
                {
                    "keywords" : {
                        "$in" : ["cricket", "women"]
                    }
                },
                {
                    "tags.id" : {
                        "$in" : ["ICC"]
                    }
                }
            ]
        }
    },
    {
        "$project": {
            "title":1,
            "_id": 0,
            "keywords": 1,
            "weight" : {
                "$size": {
                    "$setIntersection" : [
                        "$keywords" , ["cricket","women"]
                    ]
                }
            },
            "tags.id": 1
        }   
    },
    {
        "$sort": {
            "weight": -1
        }
    }
]; 
Run Code Online (Sandbox Code Playgroud)

Bla*_*ven 5

看来您的尝试已接近完成,但您当然需要实现一些东西以“匹配您的逻辑”以获得所需的最终“得分”值。

只需稍微更改投影逻辑,并假设“关键字”和“标签”都是文档中的数组,就可以了:

db.collection.aggregate([
    // Match your required documents
    { "$match": {
        "$or": [
            {
                "keywords" : {
                    "$in" : ["cricket", "women"]
                }
            },
            {
                "tags.id" : {
                    "$in" : ["ICC"]
                }
            }
        ]
    }},

    // Inspect elements and create a "weight"
    { "$project": {
        "title": 1,
        "keywords": 1,
        "tags": 1,
        "weight": {
            "$add": [
                { "$multiply": [
                    {"$size": {
                        "$setIntersection": [
                            "$keywords",
                            [ "cricket", "women" ]             
                        ]
                    }}
                ,2] },
                { "$size": {
                    "$setIntersection": [
                        { "$map": {
                            "input": "$tags",
                            "as": "t",
                            "in": "$$t.id"
                        }},
                        ["ICC"]
                    ]
                }}
            ]
        }
    }},

    // Then sort by that "weight"
    { "$sort": { "weight": -1 } }
])
Run Code Online (Sandbox Code Playgroud)

因此,$map这里的逻辑基本上是“转换”另一个数组,以提供id与所需“设置”解决方案进行比较的值。

$add运营商提供额外的“重量”到要由“重量”你的反应成员。