MongoDB Textsearch操作textSearch

时间:2017-08-03 11:20:44

标签: mongodb

我在MongoDB 3.4中进行了文本搜索,如下所示:

db.products.find({
    $text : {
        $search: '"harry potter 3"' 
    }
}, {
    score: {
        "$meta": "textScore"
    },
    name: 1,
    author_name: 1,
}).sort({
    score: {
        "$meta": "textScore"
    },
    name: 1
}).limit(9);

查询按预期工作。

示例文档是:

{ 
    "_id" : ObjectId("597f17d22be7925d9a056e82"), 
    "name" : "My cool title", 
    "author_name" : "Doe, John",
    "language" : "german",
    "keywords" : ["harry potter", "keyword 2", "keyword 3"],
    ...
}

textsearch索引位于name,keywords和author_name上。

问题:

由于我有一个德语网络商店,我想优先考虑德语文档(语言=德语)。如果你搜索"哈利波特3"我首先获得土耳其语,英语和波兰语版本(因为得分较高,因为他们有“#34;哈利波特”这个词,#34;标题两次[不知道为什么])。

那么如何为德语版本的书籍获得更高的排序位置?

只是添加一个带有{"语言":"德语"}的过滤器不是一个选项,因为我也想显示其他结果。

不起作用的想法

最好的办法是找到一种方法来提高"得分"德国书籍,但我不知道如何。这样的事情(当然这不行):

为每个文档添加一个字段language_score,并为所有德语文档提供language_score = 5,所有英语书籍language_score = 2,所有其他语言language_score = 0,然后以这种方式进行排序:

{
    score: {
        "$sum" {
            "$meta": "textScore",
            "language_score": "language_score"
        }
    },
    name: 1
}

1 个答案:

答案 0 :(得分:0)

使用聚合框架,您可以实现所需。以下查询未经测试,因为我缺少样本数据和索引设置,但您明白了这一点:

db.products.aggregate // note that we're using .aggregate() now instead of find()
(
  {
    $match: // that is the equivalent of your find() filter
    {
      $text:
      {
        $search: '"harry potter 3"' 
      }
    }
  },
  {
    $project:
    {
      "languageScore": // here we magically compute our weight
      {
        $cond:
        {
          if: { $eq: [ "$language", "german" ] },
          then: "5",
          else:
          {
            $cond:
            {
              if: { $eq: [ "$language", "english" ] },
              then: "2",
              else: 0
            }
          }
        }
      },
      score:
      {
        "$meta": "textScore"
      },
      name: 1,
      author_name: 1,
    }
  },
  {
    $sort:
    {
      languageScore: -1, // and then we can sort by that score
      score: {
        "$meta": "textScore"
      },
      name: 1
    }
  },
  { $limit: 9 }
)