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

时间:2021-08-21 02:35:41

I have a basic collection of users that have their firstName, lastName and a few other details.

我有一个基本的用户集合,它们有firstName,lastName和一些其他细节。

How would I simply search for users by a combination of both names, or partial search?

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

For example, for a collection of:

例如,对于以下集合:

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

If the search term was bob, both users would be returned since the first documents firstName is bob, and the last users lastName contains bob. If bob j was the search term, just the first document would be returned since if both names are combine, it equals Bob Jerry which matches the search term.

如果搜索项是bob,则由于第一个文档firstName是bob,并且最后一个用户lastName包含bob,因此将返回两个用户。如果bob j是搜索词,则只返回第一个文档,因为如果两个名称都是组合的,则它等于与搜索词匹配的Bob Jerry。

I tried creating a basic aggregate to concatenate the names and then make a match, although Mongoose kept throwing me an error of: Arguments must be aggregate pipeline operators.

我尝试创建一个基本聚合来连接名称,然后进行匹配,虽然Mongoose不断给我一个错误:参数必须是聚合管道运算符。

Here is my current code:

这是我目前的代码:

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

4 个解决方案

#1


3  

I see couple of mistakes in your code causing undesired result.

我发现你的代码中有几处错误会导致意外结果。

  1. Aggregation pipeline accepts array of aggregation framework operations. In your case, you are missing [] operator. It should be like

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

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

    User.aggregate([{$项目...},{$比赛...}])

  2. In $match stage you are using regex, if you are using /../ style of regex, you don't need to wrap it around string quotes. It should be /bob j/i

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

Here is finished example:

这是完成的例子:

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

You should see [ { _id: 574c3e20be214bd4078a9149, name: 'Bob Jerry' } ] on screen.

你应该在屏幕上看到[{_id:574c3e20be214bd4078a9149,名字:'Bob Jerry'}]。

#2


1  

You don't need to use the aggregation framework to select documents where the a give value is in "firstName" or "lastName".

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

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

If you want based on the concatenated value, then:

如果您想要基于连接值,那么:

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

#3


0  

The arguments for the aggregate function must be an array containing pipeline stage documents

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

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

#4


-1  

You could use $or (see the doc)

你可以使用$或(参见文档)

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

Not tested

未经测试

#1


3  

I see couple of mistakes in your code causing undesired result.

我发现你的代码中有几处错误会导致意外结果。

  1. Aggregation pipeline accepts array of aggregation framework operations. In your case, you are missing [] operator. It should be like

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

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

    User.aggregate([{$项目...},{$比赛...}])

  2. In $match stage you are using regex, if you are using /../ style of regex, you don't need to wrap it around string quotes. It should be /bob j/i

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

Here is finished example:

这是完成的例子:

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

You should see [ { _id: 574c3e20be214bd4078a9149, name: 'Bob Jerry' } ] on screen.

你应该在屏幕上看到[{_id:574c3e20be214bd4078a9149,名字:'Bob Jerry'}]。

#2


1  

You don't need to use the aggregation framework to select documents where the a give value is in "firstName" or "lastName".

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

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

If you want based on the concatenated value, then:

如果您想要基于连接值,那么:

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

#3


0  

The arguments for the aggregate function must be an array containing pipeline stage documents

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

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

#4


-1  

You could use $or (see the doc)

你可以使用$或(参见文档)

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

Not tested

未经测试