Search 2 text fields as 1 field

I am looking for users by name and I have properties: firstName

and lastName

. If I had a property fullName

it would be trivial, but I don't have it.

I want to search for "Peter Robert" and I need to combine the 2 fields into 1 abstracts before searching.

How should I do it?

+3


source to share


1 answer


Sounds mostly like you want text search . Text indexes can span multiple fields, so the entered terms from all indexed fields will be entered:

db.collection.ensureIndex({ "firstName": "text", "lastName": "text" })

db.collection.find({ "$text": { "$search": "Peter Robert" } })

      

This is one way to deal with it. Other matches will also return, but exact matches have the highest score so you can rank them.

Alternatively, if you know that, in that order, you always get a string like "Peter Robert", you can always "split" and tokenize the input:

var input = "Peter Robert";
var parts = input.split(/ /); // splits on space

db.collection.find({
    "firstName": parts[0],
    "lastName" parts[1]
])

      

It's all pretty simple. Or even to apply the operator and in the mix: $regex

$or



var input = "Peter Robert";
var regexStr = input.split(/ /).join("|");   // make it like "Peter|Robert"

db.collection.find({
    "$or": [
        { "firstName": { "$regex": regexStr } },
        { "lastName": { "$regex": regexStr }}
    ]
})

      

Honestly, you can even do it with an operator and JavaScript. Not the best though, since the condition will evaluate for every document: $where

db.collection.find(function(){
    return ( this.firstName + " " + this.lastName ) == "Peter Robert";
})

      

Probably works better with an aggregation framework:

db.collection.aggregate([
    // Borrow something from above to get "might" match documents
    { "$match": {
        "$or": [
            { "firstName": { "$regex": regexStr } },
            { "lastName": { "$regex": regexStr }}
        ]
    }},

    // Then project a "fullName"
    { "$project": {
        "firstName": 1,
        "lastName": 1,
        "fullName": { "$concat": [ "$firstName", " ", "$lastName" ] }
    }},

    // Match on the fullName value
    { "$match": { "fullName": input } }

])

      

There are many ways to do this. You are not limited to frameworks (such as those that "emulate" Mongo functionality on the client), as there are multiple ways to handle this, and server side operations such as "text search" and aggregation and "JavaScript queries" can be executed in server-side logic code.

+6


source







All Articles