在猫鼬中使用权重进行全文搜索

Posted

技术标签:

【中文标题】在猫鼬中使用权重进行全文搜索【英文标题】:Full text search with weight in mongoose 【发布时间】:2014-09-03 01:10:54 【问题描述】:

据我所知,从 3.8.9 版本开始,mongoose 支持全文搜索。但是我找不到它的好文档! 我想做类似的事情:

db.collection.ensureIndex(
    // Fields to index
    
        animal:  "text",
        color:   "text",
        pattern: "text",
        size:    "text"
    ,

    // Options
    
        name: "best_match_index",

        // Adjust field weights (default is 1)
        weights: 
            animal: 5,  // Most relevant search field
            size:   4   // Also relevant
       
    
)

我可以用纯猫鼬做吗?或者我必须使用像mongoose-text-search 这样的插件?没有重量怎么办? 我该怎么做?

【问题讨论】:

您是否尝试过在架构上调用index 来添加文本索引? 我在架构中将其作为索引:'text',但我想对多个字段进行索引,如上例所示。 不要在架构定义中声明它,调用架构的index 方法。 mongoosejs.com/docs/api.html#schema_Schema-index 你的意思是'schema.index( animal: "text", color: "text", pattern: "text", size: "text" )' ?体重呢?它是创建单个索引还是 4 个索引? 【参考方案1】:

是的,您可以在 Mongoose >= 3.8.9 中使用全文搜索。首先,一个集合最多可以有一个文本索引(参见docs)。因此,要为several fields 定义文本索引,您需要复合索引:

schema.index( animal: 'text', color: 'text', pattern: 'text', size: 'text' );

现在你可以像这样使用$text query operator:

Model
    .find(
         $text :  $search : "text to look for"  , 
         score :  $meta: "textScore"  
    )
    .sort( score :  $meta : 'textScore'  )
    .exec(function(err, results) 
        // callback
    );

这还将按相关性分数对结果进行排序。

至于weights,您可以尝试将权重选项对象传递给index() 方法(您可以在其中定义复合索引)(至少使用v4.0.1 的mongoose):

schema.index( animal: 'text', color: 'text', pattern: 'text', size: 'text' , name: 'My text index', weights: animal: 10, color: 4, pattern: 2, size: 1);

【讨论】:

返回错误:$text 查询需要一个文本索引 要为多个字段定义文本索引,您需要复合索引。确保您正确定义复合索引。 此过程是否记录在某处?我正在尝试将文本索引与猫鼬一起使用,但它不起作用。我创建了一个复合索引,我使用了像您的示例一样的 $text 运算符,但结果始终是一个空文档。 见$text doc 和text search tutorials。你的猫鼬版本是什么? (全文搜索适用于版本 >= 3.8.9) @Mallen 你找到解决方案了吗?【参考方案2】:

从 MongoDB 2.6 开始,一个集合最多可以有一个文本索引(记录在 here)。因此,您将无法使用当前版本的 MongoDB 做您想做的事情。确实,对于根据匹配位置要求不同权重的复杂文本搜索问题,您应该考虑使用完整的文本搜索解决方案,如 Solr 或 ElasticSearch。

作为 MongoDB 中的一种解决方法,您可以手动标记字段,将它们存储为关键字数组,并为它们编制索引:

animal: ["The", "quick", "brown", "fox", "jump", ..., "dog"]

然后是这样的查询

db.test.find(animal: $in: ["brown", "shoes"])

模仿文本搜索。这种方法有一些限制,例如设置它所需的手动工作,没有词干匹配,例如,将“梦想”与“梦想”匹配,停用词不会像在正常的文本索引,并且没有任何加权机制。

【讨论】:

事实上,我只有一个包含多个字段的文本索引。打击代码是 .getIndexes() 的一部分。我用mongoose-text-search 做的,我正在寻找它的纯猫鼬版本。 ` “v”:1,“key”:“_fts”:“text”,“_ftsx”:1,“ns”:“public-diary-dev.diaries”,“name”:“完整搜索-index”,“背景”:真,“权重”:“标签”:1,“文本”:1,“标题”:1,“默认语言”:“英语”,“语言覆盖”:“语言”, “文本索引版本”:1 `【参考方案3】:

我发现以下文章将我带到了http://code.tutsplus.com/tutorials/full-text-search-in-mongodb--cms-24835 我使用以下方法删除了在最佳答案中创建的索引

db.tablename.dropIndex("indexname_text")  

我用这个命令得到了索引列表

db.tablename.getIndexes()

然后我使用以下内容创建索引

db.tablename.createIndex("$**":"text")

以下命令在 Mongoose 中有效

model.find(
    $text: $search: "text you are searching for",
    score: $meta: "textScore")
    .sort(score:$meta:"textScore"
)
.exec(function(err, results) 
    `enter code here`if(!err)
    console.log('results ' + results);

else

    console.log(err);

);

【讨论】:

【参考方案4】:
    var searchQuery=new RegExp('dam', 'i');
    var query =  firstName : searchQuery ;
    Model.find(query ...

【讨论】:

这个答案就是炸弹!我浪费了最后两个小时试图将文本索引添加到我的架构中,而我只需要这个简单的答案。嘘! 是的,但是你不能创建人性化的查询避免使用正则表达式。 小心这个,因为它可能会意外导致regex denial of service vulnerability 完全同意BrotherDonkey ...请在考虑安全的情况下发布答案!

以上是关于在猫鼬中使用权重进行全文搜索的主要内容,如果未能解决你的问题,请参考以下文章

在猫鼬中,如何根据当前结果过滤搜索结果?

如何通过填充字段在猫鼬中查找文档?

如何通过填充字段在猫鼬中查找文档?

在猫鼬中执行 CRUD 操作时异步/等待

在猫鼬中匹配具有字符串值的数组?

在猫鼬中匹配具有字符串值的数组?