将2个文本字段搜索为1个字段

时间:2014-11-11 01:27:28

标签: javascript mongodb meteor mongodb-query

我要按姓名搜索用户,而且我还有以下属性:firstNamelastName。如果我有一个属性fullName,这将是微不足道的,但我没有。

我想搜索" Peter Robert"我需要在搜索之前将这两个字段组合成1个字段。

我该怎么做?

1 个答案:

答案 0 :(得分:7)

听起来基本上就像你想要一个"text search"Text indexes可以跨越多个字段,因此可以从所有索引字段中搜索输入的字词:

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

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

这是解决这个问题的一种方法。也会返回其他匹配,但完全匹配得分最高,因此您可以对其进行排名。

或者,如果你知道你总是得到像彼得罗伯特那样的字符串"按此顺序,你可以随时"拆分"并标记输入:

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

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

这一切都非常基础。甚至可以在混合中应用 $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 }}
    ]
})

老实说,您甚至可以使用 $where 运算符和JavaScript执行此操作。不是最好的,因为条件会评估每个文档:

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

但是聚合框架可能会更好一些:

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

])

许多方法都可以做到这一点。您不受框架的限制(例如那些"模拟" Mongo在客户端上运行的功能),因为有多种方法可以处理这个和服务器端操作,例如" text search"和聚合以及" JavaScript查询"都可以在服务器逻辑代码中完成。