簡體   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