我要按姓名搜索用户,而且我还有以下属性:firstName
和lastName
。如果我有一个属性fullName
,这将是微不足道的,但我没有。
我想搜索" Peter Robert"我需要在搜索之前将这两个字段组合成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查询"都可以在服务器逻辑代码中完成。