【问题标题】: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 个索引?

标签: mongodb mongoose full-text-search


【解决方案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 doctext 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 ...请在考虑安全的情况下发布答案!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-17
    • 2021-10-05
    • 2018-08-29
    • 1970-01-01
    • 1970-01-01
    • 2020-08-05
    • 2017-08-16
    相关资源
    最近更新 更多