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

时间:2015-06-25 12:01:46

标签: mongodb mongodb-query aggregation-framework

对你来说这可能听起来像是一个简单的问题,但我花了3个多小时来实现它,但我在中途陷入困境。

输入

  1. 关键字列表
  2. 标签列表
  3. 问题陈述:我需要从数据库中找到满足以下条件的所有文件:

    1. 列出包含1个或多个匹配关键字的文档。 (实现)
    2. 列出包含1个或多个匹配标记的文档。 (实现)
    3. 根据权重对找到的文件进行排序:每个关键字匹配带2个点,每个标签匹配带1个点。
    4. 查询:我如何达到要求#3。

      我的尝试:在我的尝试中,我只能根据关键字匹配列出(也不会将权重乘以2)。

      标签是文档数组。每个标签的结构类似于

      {
         "id" : "ICC",
         "some Other Key" : "some Other value"
      }
      

      关键字是字符串数组:

      ["women", "cricket"]
      

      查询:

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

1 个答案:

答案 0 :(得分:4)

您的尝试似乎很接近,但当然您需要实施一些事情来匹配您的逻辑"为了获得最终的分数"你想要的价值。

只需稍微改变您的投影逻辑,并假设两个"关键字"和"标签"是文档中的数组:

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

因此,$map逻辑基本上是"转换"另一个数组只给出id值以便与" set"进行比较。你想要的解决方案。

$add运算符提供额外的"权重"对你想要的成员"体重"你的回答。