猫鼬-搜索文本在三个领域的基础上得分或权重



我在MongoDB上使用Mongoose。这是我的模型的样子。

var BookSchema = new Schema({
  name: String,
  viewCount: { type: Number, default: 0 },
  description: {
    type: String,
    default: 'No description'
  },
  body: {
    type: String,
    default: ''
  }
    }
});

我需要在Name, Description, Body字段上搜索一些文本。到目前为止,这就是我所做的。它的工作:

Book.find().or([{ 'name': { $regex: term, $options: "$i" }}, { 'description': { $regex: term, $options: "$i" }}, { 'body': { $regex: term, $options: "$i" }}]).exec(
    function (err, topics) {
      if (err) {
        return handleError(res, err);
      }
      return res.status(200).json(books);
    });

问题:我需要想出一些机制,我分配权重/分数给所有字段(Name,Description,Body), name具有最高的权重,description具有比名称和body具有最小的权重。当结果出来时,我想按分数/权重对结果进行排序。

到目前为止,我已经查看了这个链接&权重,但不确定什么是获得预期结果的最佳方式。我也想了解,我是否需要在每次搜索之前创建权重,或者它是一次活动&如何使用Mongoose实现权重

"文本索引"和搜索确实可能是最好的选择,只要你是搜索整个单词。

在模式定义中添加文本索引非常简单:

BookSchema.index(
    {
         "name": "text",
         "description": "text",
         "body": "text"
    },
    {
        "weights": {
            "name": 5,
            "description": 2
        }
    }
)

这允许你用"set"权重来执行简单的搜索:

Book.find({ "$text": { "$search": "Holiday School Year" } })
    .select({ "score": { "$meta": "textScore" } })
    .sort({ "score": { "$meta": "textScore" } })
    .exec(function(err,result) {
    }
);

每个匹配的词将根据它所在的字段进行考虑,该字段给出了最大的权重和出现次数。

赋予权重是附加在"索引"上的,所以定义只做一次,不能改变。另一个限制是,at"文本搜索"不会查看"部分"单词。例如,"ci"不匹配"City"或"Citizen",对于这种事情,您将需要正则表达式代替。

如果你需要更多的灵活性,或者通常必须能够动态地改变结果的权重,那么你需要像聚合框架或mapReduce这样的东西。

聚合框架不能执行"逻辑"匹配操作(它可以通过$match操作符过滤,但不是"逻辑"匹配)的"正则表达式"到您的条件。如果合适的话,你可以使用单个单词和"精确"匹配。

Book.aggregate(
    [
        { "$match": {
            "$or": [
                { "name": /Holiday/ },
                { "description": /Holiday/ },
                { "body": /Holiday/ }
            ]
        }},
        { "$project": {
            "name": 1,
            "description": 1,
            "body": 1,
            "score": {
                "$add": [
                    { "$cond": [{ "$eq": [ "$name", "Holiday" ] },5,0 ] },
                    { "$cond": [{ "$eq": [ "$description", "Holiday" ] },2,0 ] },
                    { "$cond": [{ "$eq": [ "$body", "Holiday" ] },1,0 ] }
                ]
            }
        }},
        { "$sort": { "score": -1 } }
    ],
    function(err,results) {
    }
)

作为一个聚合管道使用数据结构来查询,您可以在其中更改每个执行的权重参数为您当前需要的任何参数。

MapReduce也有类似的原则,你可以在主键的一部分中包含一个计算过的"分数"作为先导元素。MapReduce自然地对这个键发出的所有输入进行排序,作为提供给reduce函数的优化。但是,您不能进一步排序或"限制"这样的结果。

相关内容

最新更新