gpt4 book ai didi

regex - MongoDB搜索和排序,具有匹配数和完全匹配

转载 作者:行者123 更新时间:2023-12-01 09:50:02 26 4
gpt4 key购买 nike

我想创建一个小的MongoDB搜索查询,在其中我要对基于完全匹​​配的结果集进行排序,然后再按否。的比赛。

例如。如果我有以下标签

Physics
11th-Physics
JEE-IIT-Physics
Physics-Physics

然后,如果我搜索“物理”,则其排序应为
Physics
Physics-Physics
11th-Physics
JEE-IIT-Physics

最佳答案

寻找您在这里谈论的“得分”是“不完美解决方案”中的一项技能。在这种情况下,“最佳匹配”从“文本搜索”开始,而“不完美”是在使用MongoDB的文本搜索功能时首先要考虑的术语。

MongoDB不是“不是”专用的“文本搜索”产品,也不是(像大多数数据库一样)试图成为一体。 “文本搜索”的全部功能保留给具有该领域专业知识的专用产品。因此,也许不是最合适的选择,但是对于那些可以忍受这些限制并且不想实现另一个引擎的人,可以选择“文本搜索”。还是!至少。

话虽如此,让我们看看可以对给定的数据样本做什么。首先在集合中设置一些数据:

db.junk.insert([
{ "data": "Physics" },
{ "data": "11th-Physics" },
{ "data": "JEE-IIT-Physics" },
{ "data": "Physics-Physics" },
{ "data": "Something Unrelated" }
])

然后,当然要“启用”文本搜索功能,然后需要使用“文本”索引类型为文档中的至少一个字段建立索引:

db.junk.createIndex({ "data": "text" })

现在已经准备就绪,让我们看一下第一个基本查询:

db.junk.find(
{ "$text": { "$search": "\"Physics\"" } },
{ "score": { "$meta": "textScore" } }
).sort({ "score": { "$meta": "textScore" } })

这将产生如下结果:

{
"_id" : ObjectId("55af83b964876554be823f33"),
"data" : "Physics-Physics",
"score" : 1.5
}
{
"_id" : ObjectId("55af83b964876554be823f30"),
"data" : "Physics",
"score" : 1
}
{
"_id" : ObjectId("55af83b964876554be823f31"),
"data" : "11th-Physics",
"score" : 0.75
}
{
"_id" : ObjectId("55af83b964876554be823f32"),
"data" : "JEE-IIT-Physics",
"score" : 0.6666666666666666
}

这样可以“接近”您想要的结果,但是当然没有“完全匹配”组件。此外,此处的文本搜索功能与 $text 运算符一起使用的逻辑意味着“物理-物理”是此处的首选匹配项。

这是因为然后引擎无法识别介于两者之间的“非单词”,例如“连字符”。为此,“物理”一词在文档的索引内容中多次出现,因此得分更高。

现在,这里的其余逻辑取决于“完全匹配”的应用以及其含义。如果要在字符串中查找“Physics”,而在“not”中用“连字符”或其他字符包围,则以下内容不适用。但是,您只能匹配“完全”只是“物理”字段的“值”:

db.junk.aggregate([
{ "$match": {
"$text": { "$search": "Physics" }
}},
{ "$project": {
"data": 1,
"score": {
"$add": [
{ "$meta": "textScore" },
{ "$cond": [
{ "$eq": [ "$data", "Physics" ] },
10,
0
]}
]
}
}},
{ "$sort": { "score": -1 } }
])

这样一来,您既可以查看引擎生成的“textScore”,又可以通过逻辑测试应用一些数学运算。在这种情况下,“数据”与“物理”完全相等,然后我们使用 $add 通过其他因素“加权”分数:

{
"_id": ObjectId("55af83b964876554be823f30"),
"data" : "Physics",
"score" : 11
}
{
"_id" : ObjectId("55af83b964876554be823f33"),
"data" : "Physics-Physics",
"score" : 1.5
}
{
"_id" : ObjectId("55af83b964876554be823f31"),
"data" : "11th-Physics",
"score" : 0.75
}
{
"_id" : ObjectId("55af83b964876554be823f32"),
"data" : "JEE-IIT-Physics",
"score" : 0.6666666666666666
}

这是 aggregation framework可以通过允许在附加条件下操作返回的数据来为您完成的工作。最终结果将传递到 $sort 阶段(请注意,它以降序反向),以使该新值成为排序键。

但是聚合框架实际上只能在字符串上处理“完全匹配”。目前尚无处理正则表达式匹配或字符串中返回投影有意义值的索引位置的工具。甚至没有逻辑上的匹配。而且 $regex 操作仅用于“过滤”查询,因此此处不使用。

因此,如果您正在“短语”中寻找比“字符串等于”完全匹配更复杂的东西,那么另一个选择是使用 mapReduce

这是另一种“不完美”的方法,因为 mapReduce命令的局限性意味着引擎通过这种查询获得的“textScore”已“完全消失”。尽管可以正确选择实际文档,但是引擎无法使用固有的“排名数据”。这是MongoDB首先将“分数”“投影”到文档中的副产品,而“投影”不是 mapReduce可用的功能。

但是您可以使用JavaScript“玩”这些字符串,如我的“不完美”示例中所示:

db.junk.mapReduce(
function() {
var _id = this._id,
score = 0;

delete this._id;

score += this.data.indexOf(search);
score += this.data.lastIndexOf(search);

emit({ "score": score, "id": _id }, this);
},
function() {},
{
"out": { "inline": 1 },
"query": { "$text": { "$search": "Physics" } },
"scope": { "search": "Physics" }
}
)

结果如下:

{
"_id" : {
"score" : 0,
"id" : ObjectId("55af83b964876554be823f30")
},
"value" : {
"data" : "Physics"
}
},
{
"_id" : {
"score" : 8,
"id" : ObjectId("55af83b964876554be823f33")
},
"value" : {
"data" : "Physics-Physics"
}
},
{
"_id" : {
"score" : 10,
"id" : ObjectId("55af83b964876554be823f31")
},
"value" : {
"data" : "11th-Physics"
}
},
{
"_id" : {
"score" : 16,
"id" : ObjectId("55af83b964876554be823f32")
},
"value" : {
"data" : "JEE-IIT-Physics"
}
}

我自己的“愚蠢的小算法”基本上是在这里同时获取匹配字符串的“第一个”和“最后一个”索引位置,并将它们加在一起以产生一个分数。这可能不是您真正想要的,但重点是,如果您可以使用JavaScript编写逻辑代码,则可以将其扔给引擎以产生所需的“排名”。

这里要记住的唯一真正的“技巧”是,“得分” 必须是此处的分组“键”的“先前”部分,并且如果包括原始文档 _id值,则该复合键部分 必须是重命名,否则 _id将具有顺序优先权。

这只是 mapReduce的一部分,其中作为“优化”,所有输出的“键”值在由化简器进行处理之前都以“升序”排序。当然,哪一个在这里什么都不做,因为我们不是在“聚合”,而是通常使用JavaScript运行程序和 mapReduce的文档重塑。

因此,总体来说,这些是可用的选项。它们都不是完美的,但是您也许可以忍受它们,甚至只是“接受”默认引擎结果。

如果您想要更多,请查看更适合的外部“专用”文本搜索产品。

旁注:此处的 $text搜索优于 $regex,因为它们可以使用索引。 “非锚定”正则表达式(不带脱字号 ^)不能在MongoDB中最佳使用索引。因此, $text搜索通常将是在短语中查找“单词”的更好基础。

关于regex - MongoDB搜索和排序,具有匹配数和完全匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31519127/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com