根据this其他问题,我正在尝试根据用户的搜索输入收集包含关键字的条目。这是针对客户的站点,架构设置如下:
{
fid: Number, // unique id for client's internal purposes
email: String,
password: String, // hashed
name: {
first: String,
last: String
},
group: {
name: String,
description: String,
type: String
},
bio: {
short: String,
long: String
}
}
这是我的疑问:
db.users.aggregate(
[{
$match: {
$or: [
{
'name.first': {
$regex: userInput,
$options: 'i'
}
},
{
'name.last': {
$regex: userInput,
$options: 'i'
}
},
{
'bio.short': {
$regex: userInput,
$options: 'i'
}
},
{
'bio.long': {
$regex: userInput,
$options: 'i'
}
}
]
},
{ $unwind: { '$name.first', '$name.last', '$bio.short', '$bio.long' } },
{
$match: {
$or: [
{
'name.first': {
$regex: userInput,
$options: 'i'
}
},
{
'name.last': {
$regex: userInput,
$options: 'i'
}
},
{
'bio.short': {
$regex: userInput,
$options: 'i'
}
},
{
'bio.long': {
$regex: userInput,
$options: 'i'
}
}
]
}
},
{ $group: { _id: '$fid', hitCount: { $sum: 1 } } },
{ $sort: { hitCount: -1 } }
}]
);
对于这种类型的查询,我不断收到意外的逗号或结束花括号。我似乎无法找到我做错的事情(我已将我的mongodb.conf详细记录为11)。我哪里出错了,我甚至走在正确的道路上?我想用除密码字段之外的所有信息返回每个条目(对象?),我该如何过滤掉它?
答案 0 :(得分:2)
对case-insensitive $regex
使用多个$or
子句并不是非常有效 - 特别是如果要搜索大量数据。 MongoDB(与2.4一样)无法有效地使用不区分大小写的正则表达式的索引(标准索引区分大小写),并且对于大字符串,匹配每个字段内的任何位置将是代价高昂的比较。 $or
子句是独立执行的,因此理想情况下,您希望在每个字段上都有一个索引(以避免完整的集合扫描),并且不区分大小写的$regex
比较仍然是一个完整的索引扫描。
针对此用例的一个更好的方法是使用MongoDB 2.4+中提供的text
indexes。文本索引不区分大小写,包括language-based word stemming,可以包含多个文本字段,并始终按相关性排序顺序返回结果。您还可以adjust the relative weights查看已编制索引的字段。
值得注意的是stemming与使用正则表达式不同。如果你想匹配单词,词干可以帮助减少公共语言根(即“运行”匹配“运行”)。
如果您匹配名称,您可能需要基于相似性或字符转置的模糊匹配方法。有关匹配名称的几种方法的详细说明,请参阅Efficient Techniques for Fuzzy and Partial matching in mongoDB。