MongoDB排序/权重$或聚合查询



我正在数据库中的两个字段上使用$或聚合进行查询。第一个条件我想比第二个条件更相关,所以我想先按第一个条件排序,然后再返回后者。

这里有一些代码:

const regexp = new RegExp('^' + req.query.search, 'i')
const query = {
$or: [{ word: regexp }, { 'lang.english': regexp }],
}
const words = await collection
.find(query, {
collation: {
locale: 'sv',
strength: 1,
},
projection: {
'-_id': 1,
'word': 1,
'lang.english': 1,
'lang.definitionEnglish': 1,
'lang.definition': 1,
},
})
.skip(skips)
.limit(page_size)
.toArray()

因此,基本上,那些在word正则表达式上匹配的结果应该首先出现,然后是lang.english

首先,让我们将一些数据放入MongoDB测试集合中进行处理。

db.test.insertMany([
{ word: 'TEST123', lang: { english: 'wibble1' } },
{ word: 'wibble2', lang: { english: 'Test123' } },
{ word: 'test345', lang: { english: 'wibble3' } },
{ word: 'wibble4', lang: { english: 'testy101' } }
]);
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5f6924b271e546940acc10f7"),
ObjectId("5f6924b271e546940acc10f8"),
ObjectId("5f6924b271e546940acc10f9"),
ObjectId("5f6924b271e546940acc10fa")
]
}

这与问题中提到的结构相同。

接下来,我们可以构建一个聚合查询,它将与您的查找结果匹配,但这次添加了一个额外的字段,我们可以对其进行排序。如果单词字段匹配,我们将使其为1,而其他字段则为2。

db.test.aggregate([
{ $match:  { $or: [{ word: regexp }, { 'lang.english': regexp }] } },
{ $addFields: { sortingValue: { $cond: { if: { $regexMatch: { input: "$word" , regex: regexp } }, then: 1, else: 2 } } } }
]);
{
"_id" : ObjectId("5f6924b271e546940acc10f7"),
"word" : "TEST123",
"lang" : {
"english" : "wibble1"
},
"sortingValue" : 1
}
{
"_id" : ObjectId("5f6924b271e546940acc10f8"),
"word" : "wibble2",
"lang" : {
"english" : "Test123"
},
"sortingValue" : 2
}
{
"_id" : ObjectId("5f6924b271e546940acc10f9"),
"word" : "test345",
"lang" : {
"english" : "wibble3"
},
"sortingValue" : 1
}
{
"_id" : ObjectId("5f6924b271e546940acc10fa"),
"word" : "wibble4",
"lang" : {
"english" : "testy101"
},
"sortingValue" : 2
}

现在我们可以添加普通排序、跳过和限制。

var regexp = new RegExp('^' + 'test', 'i')
var skip = 0;
var limit = 3;
db.test.aggregate([
{ $match:  { $or: [{ word: regexp }, { 'lang.english': regexp }] } },
{ $addFields: { sortingValue: { $cond: { if: { $regexMatch: { input: "$word" , regex: regexp } }, then: 1, else: 2 } } } },
{ $sort: { sortingValue: 1 } },
{ $skip: skip },
{ $limit: limit }
]);
{
"_id" : ObjectId("5f6924b271e546940acc10f9"),
"word" : "test345",
"lang" : {
"english" : "wibble3"
},
"sortingValue" : 1
}
{
"_id" : ObjectId("5f6924b271e546940acc10f7"),
"word" : "TEST123",
"lang" : {
"english" : "wibble1"
},
"sortingValue" : 1
}
{
"_id" : ObjectId("5f6924b271e546940acc10f8"),
"word" : "wibble2",
"lang" : {
"english" : "Test123"
},
"sortingValue" : 2
}

最新更新