繁体   English   中英

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

[英]MongoDB sort / weight $or aggregated query

我正在对数据库中的两个字段进行 $or 聚合查询。 我希望第一个条件比第二个条件更相关,所以我想先对第一个条件匹配的条件进行排序,然后再返回后者。

这是一些代码:

  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 regexp 的结果应该首先出现,然后是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")
        ]
}

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

接下来,我们可以构建一个聚合查询,它将与您的 find 匹配,但这次附加一个我们可以排序的额外字段。 如果 word 字段匹配,我们将设置为 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
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM