Mongodb 不同权重的相关性查询

Mongodb 不同权重的相关性查询,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我提供了产品搜索功能 用户可以通过多个标签进行搜索 例如,用户可以搜索“iphone,128G,美国” 如果搜索词在标题中匹配,它将得分3分 如果搜索词在标记中匹配,它将得分1分 如何重写当前查询以执行结果 文件1将获得:7分 文件2将获得:4分 样本文件1 样本文件2 当前查询 我认为您处理这个问题的方式有点错误,并且要求从数据库中进行太多的“模糊匹配”。取而代之的是,考虑修改后的数据样本: db.items.insert([ { “标题”:“iphone 6 128G”, “标签”:[

我提供了产品搜索功能

用户可以通过多个标签进行搜索

例如,用户可以搜索“iphone,128G,美国”

如果搜索词在标题中匹配,它将得分3分

如果搜索词在标记中匹配,它将得分1分

如何重写当前查询以执行结果

  • 文件1将获得:7分
  • 文件2将获得:4分
样本文件1 样本文件2 当前查询
我认为您处理这个问题的方式有点错误,并且要求从数据库中进行太多的“模糊匹配”。取而代之的是,考虑修改后的数据样本:

db.items.insert([
{
“标题”:“iphone 6 128G”,
“标签”:[
“iphone”,
“iphone6”,
“128G”,
“美国”,
“黄金”,
]
},
{
“标题”:“iphone 4 64G”,
“标签”:[
“iphone”,
“iphone4”,
“64G”,
“美国”,
“黄金”,
]
}
])
现在你会考虑这样的“搜索短语”:

“iphone4 128G美国”

然后,您需要实现自己的应用程序逻辑(不是很难,只是引用主标记),它可以扩展为以下内容:

var searchedTags=[“iphone”、“iphone4”、“128G”、“美国”]
您可以这样构造管道查询:

db.items.aggregate([
{“$match”:{“tags”:{“$in”:searchedTags}}},
{“$project”:{
"标题":一,,
“标签”:1,
“分数”:{
“$let”:{
“vars”:{
“匹配大小”:{
“$size”:{
“$setcrossion”:[
“$tags”,
搜索标签
]
}
}
},
“在”:{
“$add”:[
“$$matchSize”,
{“$cond”:[
{“$eq”:[
“$$matchSize”,
{“$size”:“$tags”}
]},
“$$matchSize”,
0
]}
]
}
}
}
}},
{“$sort”:{“score”:-1}
])
返回以下结果:

{
“_id”:ObjectId(“55b3551164518e494632fa19”),
“标题”:“iphone 6 128G”,
“标签”:[
“iphone”,
“iphone6”,
“128G”,
“美国”,
“黄金”
],
“分数”:3分
}
{
“_id”:ObjectId(“55B3551164518E49463FA1A”),
“标题”:“iphone 4 64G”,
“标签”:[
“iphone”,
“iphone4”,
“64G”,
“美国”,
“黄金”
],
“分数”:2分
}
因此,更多的“标签”匹配始终获胜

但是如果这句话改成这样的话:

“iphone4 64G美国金色”

这导致解析的标记如下所示:

var searchedTags=[“iphone”、“iphone4”、“64G”、“美国”、“黄金”]
然后,相同的查询管道会产生以下结果:

{
“_id”:ObjectId(“55B3551164518E49463FA1A”),
“标题”:“iphone 4 64G”,
“标签”:[
“iphone”,
“iphone4”,
“64G”,
“美国”,
“黄金”
],
“分数”:10分
}
{
“_id”:ObjectId(“55b3551164518e494632fa19”),
“标题”:“iphone 6 128G”,
“标签”:[
“iphone”,
“iphone6”,
“128G”,
“美国”,
“黄金”
],
“分数”:3分
}
您不仅从一个文档上提供的标签上获得了比另一个文档上提供的标签更多匹配的好处,而且因为其中一个文档匹配了“所有”提供的标签,因此有了额外的分数提升,使其在排名上比仅匹配相同数量标签的文档更进一步

要打破这一点,首先要考虑的是,表达式在流水线中为元素声明了一个“变量”,因此我们不会通过在多个地方键入相同的表达式来产生结果的<代码> $$MatxSyth值。 该变量本身是通过从

searchedTags
数组和
$tags
数组本身的。“交集”的结果只是匹配的项目,这为测试该阵列的性能提供了空间

因此,稍后在将该匹配的
$$size
归因于“分数”时,另一个考虑是通过三元组来确定
$$matchSize
是否等于
$tags
的原始长度。如果为真,则将
$$matchSize
添加到其自身(得分为“标记”长度的两倍),以作为与所提供标记的“精确匹配”,否则该条件的返回结果为
0

使用ProdCue处理这两个数字结果将为每个文档提供最终总“分数”值


这一点的要点是聚合框架缺少对字符串(如标题)进行任何形式的“模糊匹配”的操作符。尽管您可以在一个阶段内进行匹配,因为这基本上是一个查询运算符,但它只会“过滤”结果

你可以“胡闹”,但对于正则表达式来说,你真正想要的是为匹配的术语获得一个数字“分数”。这种拆分(尽管在其他语言regex操作符中可能)实际上并不可用,因此更合理的做法是简单地“标记”您的“标记”以进行输入,并将它们与文档“标记”相匹配

对于“数据库”(MongoDB主要是数据库)来说,这是一个更好的解决方案。或者你甚至可以把它和
"title": "iphone 6 128G",
"tag": [
  "usa",
  "golden",
]
"title": "iphone 4 64G",
"tag": [
  "usa",
  "golden",
]
  collection.aggregate(
     {
      "$match" => {
          "tag":{ "$in"=> q_params },
      }
     },
     { "$unwind" => "$tag" },
     { "$match" => { "tag"=> { "$in"=> q_params } } },
     { "$group" => { "_id"=> {"title":"$title"},
        "points"=> { "$sum"=>1 } } },
     { "$sort" => { "points"=> -1 } }
  )