如何使用MongoDB通过名字和姓氏搜索用户?

时间:2016-05-30 12:27:16

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

我有一个基本的用户群,他们有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) {
    ...
});

6 个答案:

答案 0 :(得分:7)

我在代码中发现了一些错误,导致了不良后果。

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

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

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

  3. 这是完成的例子:

    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' } ]

答案 1 :(得分:1)

您不需要使用聚合框架来选择给定值所在的文档" 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 } 

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

此代码已经过测试,可以正常工作:

想象这个集合像这样{name :{first:'','last:''}}

查询应如下所示:db.collectionName.find({ $or : [ { 'name.first':{ $regex: 'search', $options: '-i' } }, { 'name.last': { $regex: 'search', $options: '-i' } }, ]});

答案 5 :(得分:-2)

您可以使用$或(see the doc

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

未经测试