【问题标题】:How to search for users by both first and last name with MongoDB?如何使用 MongoDB 按名字和姓氏搜索用户?
【发布时间】:2016-09-28 06:49:10
【问题描述】:

我有一个基本的用户集合,其中包含他们的firstNamelastName 和一些其他详细信息。

如何简单地通过两个名称的组合或部分搜索来搜索用户?

例如,对于一个集合:

{
   firstName: Bob,
   lastName: Jerry
}, {
   firstName: Clark,
   lastName: Mcbobby
}

如果搜索词是bob,则将返回两个用户,因为第一个文档firstName 是bob,最后一个用户lastName 包含bob。如果bob j 是搜索词,则只会返回第一个文档,因为如果两个名称组合在一起,则等于匹配搜索词的Bob Jerry

我尝试创建一个基本的aggregate 来连接名称,然后进行匹配,尽管 Mongoose 一直向我抛出错误:Arguments must be aggregate pipeline operators

这是我当前的代码:

User.aggregate({
    $project: { "name" : { $concat : [ "$firstName", " ", "$lastName" ] } },
    $match: {"name": {$regex: "/bob j/i"}}
}).exec(function(err, results) {
    ...
});

【问题讨论】:

    标签: node.js mongodb mongoose mongodb-query aggregation-framework


    【解决方案1】:

    此代码经过测试,运行良好:

    想象一下集合是这样的{name :{first:'','last:''}}

    查询应该是这样的:db.collectionName.find({ $or : [ { 'name.first':{ $regex: 'search', $options: '-i' } }, { 'name.last': { $regex: 'search', $options: '-i' } }, ]});

    【讨论】:

      【解决方案2】:

      使用最新的 mongodb 版本 4.2,您可以使用 $regexMatch 聚合。像这样的

      db.collection.find({
        "$expr": {
          "$regexMatch": {
            "input": { "$concat": ["$firstName", " ", "$lastName"] },
            "regex": "a",  //Your text search here
            "options": "i"
          }
        }
      })
      

      【讨论】:

        【解决方案3】:

        我发现您的代码中有几个错误导致了不希望的结果。

        1. 聚合管道接受聚合框架操作数组。在您的情况下,您缺少 [] 运算符。应该是这样的

          User.aggregate([{$project...},{$match...}])

        2. 在 $match 阶段,您使用的是正则表达式,如果您使用的是/../ 正则表达式样式,则不需要将其包裹在字符串引号中。应该是/bob j/i

        这是完成的例子:

        User.aggregate([
          {$project: { "name" : { $concat : [ "$firstName", " ", "$lastName" ] } }},
          {$match: {"name": {$regex: /bob j/i}}}
        ]).exec(function(err, result){
          console.log(result);
        });
        

        您应该会在屏幕上看到[ { _id: 574c3e20be214bd4078a9149, name: 'Bob Jerry' } ]

        【讨论】:

        • 啊,好吧,因为我的聚合管道不是数组,所以抛出了错误。感谢 Saleem,您的修复工作完美无缺。
        【解决方案4】:

        您不需要使用聚合框架来选择给定值在“firstName”或“lastName”中的文档。

        var reg = new RegExp(/bob/, 'i');
        User.find({
            '$or': [
                { 'firstName': reg }, 
                { 'lastName': reg }
            ]
        }).exec(function(err, results) { // Do something }
        

        如果你想基于串联值,那么:

        User.aggregate([
            { "$project": { "name": { "$concat" : [ "$firstName", " ", "$lastName" ] } } },  
            { "$match" : { "name": /bob j/i } }  
        ]).exec(function(err, results) { // Do something } 
        

        【讨论】:

          【解决方案5】:

          聚合函数的参数必须是一个包含管道阶段文档的数组

          var query = 'bob j';
          Users.aggregate([ //pipeline array
           {$project:{name: { $concat : [ "$firstName", " ", "$lastName" ] }}}, //stage1
           {$match : { name: { $regex: query, $options:'i'}}} //stage2
          ])
          

          【讨论】:

            【解决方案6】:

            你可以使用 $or (see the doc)

            User.find({ $or: [
              {$match: {"firstName": {$regex: "/bob j/i"}}},
              {$match: {"lastName": {$regex: "/bob j/i"}}}
            ] });
            

            未测试

            【讨论】:

            • 不匹配“firstName”或“lastName”吗?因此,“bob j”也不匹配,因为它是两者的组合?
            猜你喜欢
            • 2015-08-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-05-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-09-02
            相关资源
            最近更新 更多