【问题标题】:如何使用“like”查询 MongoDB
【发布时间】:2011-03-19 08:19:29
【问题描述】:

我想用 SQL 的 like 查询来查询一些东西:

SELECT * FROM users  WHERE name LIKE '%m%'

如何在 MongoDB 中实现相同的目标?我在the documentation 中找不到like 的运算符。

【问题讨论】:

标签: sql mongodb mongodb-query sql-like


【解决方案1】:

您可以在 MongoDB 中使用正则表达式。

例如,

db.users.find({"name": /^m/})

【讨论】:

  • 我认为这只会显示名称值以“m”开头的文档
  • 使用正则表达式时删除引号很重要,即不要执行“/^m/”,只需执行/^m/
【解决方案2】:

那应该是:

db.users.find({"name": /.*m.*/})

或者,类似的:

db.users.find({"name": /m/})

您正在查找某处包含“m”的内容(SQL 的“%”运算符等效于正则表达式“.*”),而不是“m”锚定到字符串开头的内容.

注意: MongoDB 使用的正则表达式比 SQL 中的“LIKE”更强大。使用正则表达式,您可以创建您想象的任何模式。

有关正则表达式的更多信息,请参阅Regular expressions (MDN)。

【讨论】:

  • 通过正则表达式搜索是否昂贵?
  • 实际上,这取决于。如果查询不使用索引,并且必须进行表扫描,那么它肯定会很昂贵。如果您正在执行“开始于”正则表达式查询,那么可以使用索引。最好运行一个 explain() 来查看发生了什么。
  • 当不锚定到字符串的开头时,它有点昂贵。但话说回来,SQL 中的LIKE 查询也是如此。
  • 我会添加正则表达式 i javascript db.users.find({ "name": { $regex: /m/i } })
  • 值得一提的是,如果你想从 Node 应用程序中使用它并且想要动态搜索,你可以使用:users.find({"name": new RegExp('.*' + searchVariable + '.*')}) 所以,这样你就可以将它与其他运算符一起使用,例如 $in , $nin 等。
【解决方案3】:

在 PHP 中,您可以使用以下代码:

$collection->find(array('name'=> array('$regex' => 'm'));

【讨论】:

    【解决方案4】:

    • PyMongo 使用 Python
    • Mongoose 使用 Node.js
    • Jongo,使用 Java
    • mgo,使用 Go

    你可以这样做:

    db.users.find({'name': {'$regex': 'sometext'}})
    

    【讨论】:

    • @TahirYasin 如果您仍然想知道,不区分大小写的搜索可以这样完成:db.users.find({'name': {'$regex': 'sometext', '$options': 'i'}})
    • 这适用于整个单词,而不是单词的一部分。
    【解决方案5】:

    您可以使用 where 语句来构建任何 JavaScript 脚本:

    db.myCollection.find( { $where: "this.name.toLowerCase().indexOf('m') >= 0" } );
    

    参考:$where

    【讨论】:

    • $where 效率极低。做完整的收藏扫描:(
    【解决方案6】:

    如果使用 Node.jsit says 可以这样写:

    db.collection.find( { field: /acme.*corp/i } );
    
    // Or
    db.collection.find( { field: { $regex: 'acme.*corp', $options: 'i' } } );
    

    Also,你可以这样写:

    db.collection.find( { field: new RegExp('acme.*corp', 'i') } );
    

    【讨论】:

    • 谢谢@Eddy。使用正则表达式提供 '$options: 'i'' 使重构过程对我来说很容易。
    【解决方案7】:

    在 Go 和 mgo 驱动程序中:

    Collection.Find(bson.M{"name": bson.RegEx{"m", ""}}).All(&result)
    

    结果是广受欢迎的类型的结构实例。

    【讨论】:

    • 请避免在文字中使用无键字段,改为使用bson:RegEx{Pattern:"m", Options:"i"}
    【解决方案8】:

    在 SQL 中,“like”查询如下所示:

    select * from users where name like '%m%'
    

    在 MongoDB 控制台中,它看起来像这样:

    db.users.find({"name": /m/})     // Not JSON formatted
    
    db.users.find({"name": /m/}).pretty()  // JSON formatted
    

    另外,pretty() 方法会在所有地方生成一个格式化的 JSON 结构,这样更易​​读。

    【讨论】:

      【解决方案9】:
      db.users.insert({name: 'paulo'})
      db.users.insert({name: 'patric'})
      db.users.insert({name: 'pedro'})
      

      因此:

      为:

      db.users.find({name: /a/})  // Like '%a%'
      

      输出:paulo, patric

      为:

      db.users.find({name: /^pa/}) // Like 'pa%'
      

      输出:paulo, patric

      为:

      db.users.find({name: /ro$/}) //like '%ro'
      

      输出:pedro

      【讨论】:

      • 你知道为什么你有这么多的赞成票吗?因为文档应该得到同样多的反对票!谢谢
      【解决方案10】:

      您可以使用 MongoDB 2.6 的新功能:

      db.foo.insert({desc: "This is a string with text"});
      db.foo.insert({desc:"This is a another string with Text"});
      db.foo.ensureIndex({"desc":"text"});
      db.foo.find({
          $text:{
              $search:"text"
          }
      });
      

      【讨论】:

      • 注意,AFAIK Mongodb 的文本搜索默认只对整个单词起作用,所以这将匹配诸如“这是一个带文本的字符串”之类的值,而不是“这是一个带潜台词的字符串”。所以它不太像 sql 的“LIKE”操作符。
      【解决方案11】:

      对于 PHP mongo 喜欢

      我在使用 PHP mongo like 时遇到了几个问题。我发现连接正则表达式参数在某些情况下会有所帮助 - PHP mongo find field starts with

      例如,

      db()->users->insert(['name' => 'john']);
      db()->users->insert(['name' => 'joe']);
      db()->users->insert(['name' => 'jason']);
      
      // starts with
      $like_var = 'jo';
      $prefix = '/^';
      $suffix = '/';
      $name = $prefix . $like_var . $suffix;
      db()->users->find(['name' => array('$regex'=>new MongoRegex($name))]);
      output: (joe, john)
      
      // contains
      $like_var = 'j';
      $prefix = '/';
      $suffix = '/';
      $name = $prefix . $like_var . $suffix;
      db()->users->find(['name' => array('$regex'=>new MongoRegex($name))]);
      
      output: (joe, john, jason)
      

      【讨论】:

        【解决方案12】:

        您已经得到答案,但要匹配不区分大小写的正则表达式,您可以使用以下查询:

        db.users.find ({ "name" : /m/i } ).pretty()
        

        /m/i 中的 i 表示不区分大小写,.pretty() 提供更漂亮的输出。

        【讨论】:

          【解决方案13】:

          如果你使用的是 Spring-Data MongoDB,你可以这样:

          String tagName = "m";
          Query query = new Query();
          query.limit(10);
          query.addCriteria(Criteria.where("tagName").regex(tagName));
          

          【讨论】:

            【解决方案14】:

            like 查询如下所示:

            db.movies.find({title: /.*Twelve Monkeys.*/}).sort({regularizedCorRelation : 1}).limit(10);
            

            对于 Scala ReactiveMongo API,

            val query = BSONDocument("title" -> BSONRegex(".*" + name + ".*", "")) // like
            val sortQ = BSONDocument("regularizedCorRelation" -> BSONInteger(1))
            val cursor = collection.find(query).sort(sortQ).options(QueryOpts().batchSize(10)).cursor[BSONDocument]
            

            【讨论】:

              【解决方案15】:

              Node.js 项目中并使用 Mongoose,使用 like 查询:

              var User = mongoose.model('User');
              
              var searchQuery = {};
              searchQuery.email = req.query.email;
              searchQuery.name = {$regex: req.query.name, $options: 'i'};
              User.find(searchQuery, function(error, user) {
                              if(error || user === null) {
                                  return res.status(500).send(error);
                              }
                              return res.status(200).send(user);
                          });
              

              【讨论】:

                【解决方案16】:

                对于 Node.js 中的 Mongoose

                db.users.find({'name': {'$regex': '.*sometext.*'}})
                

                【讨论】:

                  【解决方案17】:

                  使用正则表达式匹配如下。 'i' 表示不区分大小写。

                  var collections = mongoDatabase.GetCollection("Abcd");
                  
                  var queryA = Query.And(
                           Query.Matches("strName", new BsonRegularExpression("ABCD", "i")), 
                           Query.Matches("strVal", new BsonRegularExpression("4121", "i")));
                  
                  var queryB = Query.Or(
                         Query.Matches("strName", new BsonRegularExpression("ABCD","i")),
                         Query.Matches("strVal", new BsonRegularExpression("33156", "i")));
                  
                  var getA = collections.Find(queryA);
                  var getB = collections.Find(queryB);
                  

                  【讨论】:

                    【解决方案18】:

                    由于 MongoDB shell 支持正则表达式,这是完全可能的。

                    db.users.findOne({"name" : /.*sometext.*/});
                    

                    如果我们希望查询不区分大小写,可以使用“i”选项,如下所示:

                    db.users.findOne({"name" : /.*sometext.*/i});
                    

                    【讨论】:

                      【解决方案19】:

                      以下是使用正则表达式进行字符串搜索的不同类型的要求和解决方案。

                      您可以使用包含单词的正则表达式,即 like。您也可以使用$options => i 进行不区分大小写的搜索。

                      包含string

                      db.collection.find({name:{'$regex' : 'string', '$options' : 'i'}})
                      

                      不包含string,只有正则表达式

                      db.collection.find({name:{'$regex' : '^((?!string).)*$', '$options' : 'i'}})
                      

                      不区分大小写string

                      db.collection.find({name:{'$regex' : '^string$', '$options' : 'i'}})
                      

                      string开头

                      db.collection.find({name:{'$regex' : '^string', '$options' : 'i'}})
                      

                      string结尾

                      db.collection.find({name:{'$regex' : 'string$', '$options' : 'i'}})
                      

                      保留 Regular Expressions Cheat Sheet 作为书签,以及您可能需要的任何其他更改的参考。

                      【讨论】:

                      • 这是稍后的评论,但是,如何在上面的示例中使用变量?比如 let name = 'john doe' 。如何在正则表达式中实现名称变量?谢谢
                      【解决方案20】:

                      如果您想在 MongoDB 中进行“喜欢”搜索,那么您应该使用 $regex。通过使用它,查询将是:

                      db.product.find({name:{$regex:/m/i}})
                      

                      更多信息,您也可以阅读文档 - $regex

                      【讨论】:

                        【解决方案21】:

                        我找到了一个免费工具,可以将 MySQL 查询转换为 MongoDB:http://www.querymongo.com/

                        我检查了几个查询。在我看来,几乎所有这些都是正确的。据此,答案是

                        db.users.find({
                            "name": "%m%"
                        });
                        

                        【讨论】:

                          【解决方案22】:

                          似乎有理由同时使用 JavaScript /regex_pattern/ 模式和 MongoDB {'$regex': 'regex_pattern'} 模式。见:MongoDB RegEx Syntax Restrictions

                          这不是一个完整的正则表达式教程,但在看到highly voted ambiguous post above 之后,我受到启发运行这些测试。

                          > ['abbbb','bbabb','bbbba'].forEach(function(v){db.test_collection.insert({val: v})})
                          
                          > db.test_collection.find({val: /a/})
                          { "val" : "abbbb" }
                          { "val" : "bbabb" }
                          { "val" : "bbbba" }
                          
                          > db.test_collection.find({val: /.*a.*/})
                          { "val" : "abbbb" }
                          { "val" : "bbabb" }
                          { "val" : "bbbba" }
                          
                          > db.test_collection.find({val: /.+a.+/})
                          { "val" : "bbabb" }
                          
                          > db.test_collection.find({val: /^a/})
                          { "val" : "abbbb" }
                          
                          > db.test_collection.find({val: /a$/})
                          { "val" : "bbbba" }
                          
                          > db.test_collection.find({val: {'$regex': 'a$'}})
                          { "val" : "bbbba" }
                          

                          【讨论】:

                            【解决方案23】:

                            MongoRegex 已被弃用。

                            使用 MongoDB\BSON\Regex

                            $regex = new MongoDB\BSON\Regex ( '^m');
                            $cursor = $collection->find(array('users' => $regex));
                            //iterate through the cursor
                            

                            【讨论】:

                              【解决方案24】:

                              如果您使用的是 PHP,则可以使用 MongoDB_DataObject 包装器,如下所示:

                              $model = new MongoDB_DataObject();
                              
                              $model->query("select * from users where name like '%m%'");
                              
                              while($model->fetch()) {
                                  var_dump($model);
                              }
                              

                              或者

                              $model = new MongoDB_DataObject('users);
                              
                              $model->whereAdd("name like '%m%'");
                              
                              $model->find();
                              
                              while($model->fetch()) {
                                  var_dump($model);
                              }
                              

                              【讨论】:

                                【解决方案25】:

                                使用 MongoDB Compass,您需要使用严格模式语法,例如:

                                { "text": { "$regex": "^Foo.*", "$options": "i" } }
                                

                                (在 MongoDB Compass 中,使用 " 而不是 ' 很重要)

                                【讨论】:

                                  【解决方案26】:

                                  你有两个选择:

                                  db.users.find({"name": /string/})
                                  

                                  db.users.find({"name": {"$regex": "string", "$options": "i"}})
                                  

                                  对于第二个,您有更多选项,例如选项中的“i”以不区分大小写的方式查找。

                                  关于“字符串”,你可以使用like ".string." (%string%), 或者 "string.*" (string%) 和 ".*string) (% string) 例如。您可以根据需要使用正则表达式。

                                  【讨论】:

                                    【解决方案27】:

                                    FullName like 'last' with status=='Pending' 在两个日期之间:

                                    db.orders.find({
                                          createdAt:{$gt:ISODate("2017-04-25T10:08:16.111Z"),
                                          $lt:ISODate("2017-05-05T10:08:16.111Z")},
                                          status:"Pending",
                                          fullName:/last/}).pretty();
                                    

                                    status== 'Pending' 和 orderId LIKE 'PHA876174':

                                    db.orders.find({
                                         status:"Pending",
                                         orderId:/PHA876174/
                                         }).pretty();
                                    

                                    【讨论】:

                                      【解决方案28】:

                                      用途:

                                      db.customer.find({"customerid": {"$regex": "CU_00000*", "$options": "i"}}).pretty()
                                      

                                      当我们搜索字符串模式时,最好使用上面的模式,因为当我们不确定大小写时。

                                      【讨论】:

                                        【解决方案29】:
                                        >> db.car.distinct('name')
                                        [ "honda", "tat", "tata", "tata3" ]
                                        
                                        >> db.car.find({"name":/. *ta.* /})
                                        

                                        【讨论】:

                                        • 哇,这可能是一个了不起的答案。想详细说明一下吗?
                                        • 使用您的解决方案来回答问题中的给定示例。不要创建一个功能看似重叠的随机场景并期望它看起来很清晰。
                                        【解决方案30】:

                                        使用聚合子串搜索(带索引!!!):

                                        db.collection.aggregate([{
                                                $project : {
                                                    fieldExists : {
                                                        $indexOfBytes : ['$field', 'string']
                                                    }
                                                }
                                            }, {
                                                $match : {
                                                    fieldExists : {
                                                        $gt : -1
                                                    }
                                                }
                                            }, {
                                                $limit : 5
                                            }
                                        ]);
                                        

                                        【讨论】:

                                        • 这可能仍然比所有这些正则表达式建议更好 - 但它仍然会进行 colscan。
                                        猜你喜欢
                                        • 2011-08-02
                                        • 1970-01-01
                                        • 1970-01-01
                                        • 1970-01-01
                                        • 2016-01-05
                                        • 2017-11-25
                                        • 2016-01-24
                                        • 1970-01-01
                                        • 1970-01-01
                                        相关资源
                                        最近更新 更多