问题描述
我有一个MongoDB作为数据库,后端是用node.js编写的。我正在尝试搜索一个表,该表将返回所有与输入的字符串和字符串匹配的结果。
例如,搜索“ foo”将返回(按此顺序)
目前我有这个,但是我相信有一种更好的方法可以做到,而无需两次搜索数据库:
async function(req,res) {
var customerName = req.params.customerName;
//word match
var customers1 = await Models.DummyContactTable.find({
customerName: {
$regex: "^" + customerName,$options: 'i'
},IsActive: true
});
//String match
var customers2 = await Models.DummyContactTable.find({
$and: [
{
customerName: {
$regex: customerName,$options: 'i'
}
},{
customerName: {
$not: {
$regex: "^" + customerName,}
},IsActive: true
}
]
});
//Since sometimes we get duplicates,doing a filter and find to de-dup
var customers = customers1.concat(customers2.filter((customer) => !customers1.find(f => f.uuid === customer.uuid)));
解决方法
如果您使用的是Atlas Search,则可以编写如下查询:
{
$search: {
autocomplete: {
path: "customerName",query: "foo"
}}}
// atlas search index definition
{
"mappings": {
"fields": {
"customerName" : {
"type" : "autocomplete"
}}}
如果您需要控制结果分数,可以使用compound
{
$search: {
compound: {
should: [
{autocomplete: {path: "customerName",query: "foo" }},{text: {path: "customerName",query: "foo",score: { boost: { "value" : 3" }}}}
]}}}
在这种情况下,我们使用text
运算符通过lucene.standard
分析器对单词边界进行分割,并将这些结果提升到上面。来自Atlas Search的结果将自动按得分排序,并排在最前面。查询已针对性能进行了优化,该查询将一次性完成。
根据您的排序和查询需求(例如使用不同的分析器,前缀搜索,短语搜索,正则表达式等),还有许多其他旋钮in the docs可以打开。
,如果您想要这些类型的订购规则,我会将所有客户名称加载到一个应用程序中,该应用程序将进行搜索并完全在该应用程序中执行搜索和排序。我什至都不希望Atlas搜索提供这种灵活性。
(我也不认为您提供的查询也可以实现您想要的排序。)