我在 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
权重最小。当结果出来时,我想按分数/权重对结果进行排序。
到目前为止,我已经研究过这个 link & weights ,但不确定获得所需结果的最佳方法是什么。我还想了解,我是否需要在每次搜索之前创建权重,或者它是一次性事件以及如何使用 Mongoose 实现权重?
最佳答案
一个"text index"和 search只要您搜索整个单词,这确实可能是最好的选择。
将文本索引添加到架构定义中非常简单:
BookSchema.index(
{
"name": "text",
"description": "text",
"body": "text"
},
{
"weights": {
"name": 5,
"description": 2
}
}
)
这允许您通过“设置”字段权重来执行简单搜索:
Book.find({ "$text": { "$search": "Holiday School Year" } })
.select({ "score": { "$meta": "textScore" } })
.sort({ "score": { "$meta": "textScore" } })
.exec(function(err,result) {
}
);
每个匹配的术语将根据它所在的字段进行考虑,该字段给出了最大的权重和出现次数。
权重的分配是附加在“索引”上的,因此定义一旦完成就无法更改。另一个限制是“文本搜索”不查看“部分”单词。例如,“ci”与“City”或“Citizen”不匹配,为此您需要一个正则表达式。
如果您需要更多的灵活性,或者通常必须能够动态更改结果的权重,那么您需要聚合框架或 mapReduce 之类的东西。
但是聚合框架无法执行"logical" match将“正则表达式”操作(它可以通过 $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 会自然地对该键发出的所有输入进行排序,作为馈送到归约函数的优化。但是您无法进一步排序或“限制”这样的结果。
这些通常是您查看并决定最适合您情况的选项。
关于node.js - Mongoose - 根据分数或权重在三个字段中搜索文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32063998/