带有部分字符串的 Mongoose text-search
Mongoose text-search with partial string
你好,我正在使用 mongoose 来搜索我 collection 中的人。
/*Person model*/
{
name: {
first: String,
last: String
}
}
现在我想搜索有疑问的人:
let regex = new RegExp(QUERY,'i');
Person.find({
$or: [
{'name.first': regex},
{'name.last': regex}
]
}).exec(function(err,persons){
console.log(persons);
});
如果我搜索 John,我会得到结果(如果我搜索 Jo 的事件)。
但是,如果我搜索 John Doe,显然我没有得到任何结果。
如果我将 QUERY 更改为 John|Doe 我会得到结果,但是 returns 所有拥有 John 或 Doe 在他们的 last-/firstname.
下一步是尝试使用猫鼬文本搜索:
首先将字段添加到索引:
PersonSchema.index({
name: {
first: 'text',
last: 'text'
}
},{
name: 'Personsearch index',
weights: {
name: {
first : 10,
last: 10
}
}
});
然后修改Person查询:
Person.find({
$text : {
$search : QUERY
}
},
{ score:{$meta:'textScore'} })
.sort({ score : { $meta : 'textScore' } })
.exec(function(err,persons){
console.log(persons);
});
这很好用! 但是现在只返回与整体匹配的人first-/lastname:
-> 约翰 returns 值
-> Jo returns 无值
有办法解决吗?
答案没有外部插件是首选,但也希望有其他答案。
您可以使用 aggregate
管道执行此操作,该管道使用 $concat
将名字和姓氏连接在一起,然后对其进行搜索:
let regex = new RegExp(QUERY,'i');
Person.aggregate([
// Project the concatenated full name along with the original doc
{$project: {fullname: {$concat: ['$name.first', ' ', '$name.last']}, doc: '$$ROOT'}},
{$match: {fullname: regex}}
], function(err, persons) {
// Extract the original doc from each item
persons = persons.map(function(item) { return item.doc; });
console.log(persons);
});
但是,性能是一个问题,因为它不能使用索引,因此需要进行完整的集合扫描。
您可以通过在 $project
阶段之前使用 $match
查询来缓解这种情况, 可以 使用索引来减少其余部分的文档集管道需要查看。
因此,如果您分别索引 name.first
和 name.last
,然后将搜索字符串的第一个词作为锚定查询(例如 /^John/i
),您可以在前面添加以下内容管道的开头:
{$match: $or: [
{'name.first': /^John/i},
{'name.last': /^John/i}
]}
显然您需要以编程方式生成 "first word" 正则表达式,但希望它能给您启发。
regex 可以帮助你。
Person.find({ "name": { "$regex": "Alex", "$options": "i" } },
function(err,docs) {
});
a). 在集合中的单个字段中进行部分文本搜索:
如果我们想在集合中的单个字段中搜索,我们可以在聚合中使用该代码
{
$match: {
name: {
$regex: “String seraching”,
‘$options’: ‘i’
}
}
}
b). 通过集合中的多个字段进行部分文本搜索:
如果我们想在特定集合中通过多个字段(多个字段)进行搜索,那么我们可以在聚合查询中使用该代码
{
$match: {
$or: [
{ name: {
$regex: “String to be searched”,
‘$options’: ‘i’
}},
{ email: {
$regex: String to be searched,
‘$options’: ‘i’
}}
]
}
},
你好,我正在使用 mongoose 来搜索我 collection 中的人。
/*Person model*/
{
name: {
first: String,
last: String
}
}
现在我想搜索有疑问的人:
let regex = new RegExp(QUERY,'i');
Person.find({
$or: [
{'name.first': regex},
{'name.last': regex}
]
}).exec(function(err,persons){
console.log(persons);
});
如果我搜索 John,我会得到结果(如果我搜索 Jo 的事件)。 但是,如果我搜索 John Doe,显然我没有得到任何结果。
如果我将 QUERY 更改为 John|Doe 我会得到结果,但是 returns 所有拥有 John 或 Doe 在他们的 last-/firstname.
下一步是尝试使用猫鼬文本搜索:
首先将字段添加到索引:
PersonSchema.index({
name: {
first: 'text',
last: 'text'
}
},{
name: 'Personsearch index',
weights: {
name: {
first : 10,
last: 10
}
}
});
然后修改Person查询:
Person.find({
$text : {
$search : QUERY
}
},
{ score:{$meta:'textScore'} })
.sort({ score : { $meta : 'textScore' } })
.exec(function(err,persons){
console.log(persons);
});
这很好用! 但是现在只返回与整体匹配的人first-/lastname:
-> 约翰 returns 值
-> Jo returns 无值
有办法解决吗?
答案没有外部插件是首选,但也希望有其他答案。
您可以使用 aggregate
管道执行此操作,该管道使用 $concat
将名字和姓氏连接在一起,然后对其进行搜索:
let regex = new RegExp(QUERY,'i');
Person.aggregate([
// Project the concatenated full name along with the original doc
{$project: {fullname: {$concat: ['$name.first', ' ', '$name.last']}, doc: '$$ROOT'}},
{$match: {fullname: regex}}
], function(err, persons) {
// Extract the original doc from each item
persons = persons.map(function(item) { return item.doc; });
console.log(persons);
});
但是,性能是一个问题,因为它不能使用索引,因此需要进行完整的集合扫描。
您可以通过在 $project
阶段之前使用 $match
查询来缓解这种情况, 可以 使用索引来减少其余部分的文档集管道需要查看。
因此,如果您分别索引 name.first
和 name.last
,然后将搜索字符串的第一个词作为锚定查询(例如 /^John/i
),您可以在前面添加以下内容管道的开头:
{$match: $or: [
{'name.first': /^John/i},
{'name.last': /^John/i}
]}
显然您需要以编程方式生成 "first word" 正则表达式,但希望它能给您启发。
regex 可以帮助你。
Person.find({ "name": { "$regex": "Alex", "$options": "i" } },
function(err,docs) {
});
a). 在集合中的单个字段中进行部分文本搜索:
如果我们想在集合中的单个字段中搜索,我们可以在聚合中使用该代码
{
$match: {
name: {
$regex: “String seraching”,
‘$options’: ‘i’
}
}
}
b). 通过集合中的多个字段进行部分文本搜索:
如果我们想在特定集合中通过多个字段(多个字段)进行搜索,那么我们可以在聚合查询中使用该代码
{
$match: {
$or: [
{ name: {
$regex: “String to be searched”,
‘$options’: ‘i’
}},
{ email: {
$regex: String to be searched,
‘$options’: ‘i’
}}
]
}
},