【问题标题】:MongoDB search multiple fields matching parts of a stringMongoDB搜索匹配字符串部分的多个字段
【发布时间】:2017-04-01 18:51:06
【问题描述】:

这是对我的 MongoDB 和 NodeJs 开发人员的挑战

我有一个搜索表单,用户可以在其中输入以下内容:

225/65R16 71T K715 Hankook

至于我的 mongodb,我有一个包含以下文档的集合:

1- { _id: SomeId, Description: 225/65R16 71T K715, Brand: Hankook, Ref: 123455 }
2- { _id: SomeId, Description: 225/65R16 71T K715, Brand: Continental, Ref: 123456 }
3- { _id: SomeId, Description: 225/65R16 94T Energy, Brand: Hankook, Ref: 123457 }

我怎样才能做到这一点,以便在搜索下面的任何组合时得到上面文档 1 和 3 的结果?

组合列表:

Hankook
225/65R16
225/65R16 Hankook
225 Hankook
225 Han

【问题讨论】:

  • 该组合列表不可能:71T 在文档 #2 中。此外,没有办法与文档 #3 匹配。但是,如果您想在庄园中进行搜索,您应该查看文本搜索索引。这是一篇好文章:code.tutsplus.com/tutorials/…
  • 编辑了这个问题,因为我在列表中的最后 2 个项目是一个不好的例子。我想一个更好的问题是如何搜索匹配任何一个或两个字段(描述和品牌)的值
  • 您可以使用$or 运算符:docs.mongodb.com/v3.2/reference/operator/query/or

标签: node.js mongodb mongoose mongodb-query


【解决方案1】:

这是一个基于 node.js、javascript 和 mongoose 的示例

您可以像这样在集合的多个字段中查找“搜索词”或“搜索词”:

var searchTerm = 'Hankook'; // put your search term here

YourMongooseModel.find({ 
    $or: [
        // in this example we want to search at two fields 'Description' and 'Brand'
        // however you can put any fields as you desire
        {"Description": {$regex: searchTerm, $options: "i"}},
        {"Brand": {$regex: searchTerm, $options: "i"}}
    ]
}, function (err, docs) {
    if(docs) {
        // handle retreived docs here
    }
});

希望这会有所帮助。谢谢

【讨论】:

    【解决方案2】:

    使用聚合来连接搜索字段,然后简单地使用正则表达式:

    // Build a regex from your string,
    // Example : containing exactly all word, no order
    enter code here
    var a = "225/65R16 71T K715 Hankook"
    var ar = a.split(new RegExp("\\s")); // [ '225/65R16', '71T', 'K715', 'Hankook' ]
    var estr = ""
    ar.forEach(function(e){ estr += "(?=.*\b"+e+"\b)";});
    var re = new RegExp("^.*"+estr+".*$"); // /^.*(?=.*\b225\/65R16\b)(?=.*\b71T\b)(?=.*\bK715\b)(?=.*\bHankook\b).*$/
    
    
    
    enter code here
    db.a.aggregate([
       {
           $project:{
              st: {$concat:["$Brand"," ", "$Description"]}, 
             _id:1,
             Description:1,
             Brand:1,
             Ref:1
           }
       },
       {
          $match:{
             st: /^(?=.*\b225\/65R16\b)(?=.*\b71T\b)(?=.*\bK715\b)(?=.*\bHankook\b).*$/
          }
       }
    ])
    
    // output { "_id" : ObjectId("582f009da52585177f054ddc"), "Description" : "225/65R16 71T K715", "Brand" : "Hankook", "Ref" : "123455", "st" : "Hankook 225/65R16 71T K715" }
    

    【讨论】:

      【解决方案3】:

      您可以使用regular expressions 匹配字段的开头,然后使用OR operator

      假设有以下文件。

      { "Description" : "225/65R16 71T K715", "Brand" : "Hankook", "Ref" : 123455 }
      { "Description" : "225/65R16 71T K715", "Brand" : "Continental", "Ref" : 123455 }
      { "Description" : "225/65R16 94T", "Brand" : "Hankook", "Ref" : 123455 }
      

      以下查询返回预期结果。

      > db.test.find({$or: [{Description: {$regex: '^225/65R16'}, Brand: {$regex: '^Hankook'}}]})
      { "Description" : "225/65R16 71T K715", "Brand" : "Hankook", "Ref" : 123455 }
      {"Description" : "225/65R16 94T", "Brand" : "Hankook", "Ref" : 123455 }
      
      > db.test.find({$or: [{Description: {$regex: '^225'}, Brand: {$regex: '^Han'}}]})
      { "Description" : "225/65R16 71T K715", "Brand" : "Hankook", "Ref" : 123455 }
      { "Description" : "225/65R16 94T", "Brand" : "Hankook", "Ref" : 123455 }
      

      对于225/65R16,虽然无法避免匹配文档编号 2,因为查询不包含足够的消歧信息。

      【讨论】:

        【解决方案4】:

        您可以尝试创建一个索引:

        db.yourollection.createIndex({"Description":1,"Brand":1})
        

        然后通过搜索值,示例:

        mongoosemodel.find({$text:{$search: 225/65R16 Hankook}},{Description:1,Brand:1})
        

        而且,如果您得到的结果超出预期,您可以使用 Javascript 进行过滤。

        【讨论】:

        • 可能是最好的答案。正则表达式将按照其他答案所指出的那样工作,但它不可扩展,因为它不使用您的索引。因此,您的轮胎集合越大,这些查询就会变得越慢。
        猜你喜欢
        • 1970-01-01
        • 2021-04-17
        • 2015-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多