【问题标题】:$sort with least value inside an array mongodb$sort 在数组 mongodb 中具有最小值
【发布时间】:2018-12-28 01:11:14
【问题描述】:

我在数据库中有以下文件。我想要的是能够通过数组内的一个子文档的值对文档进行排序。这可能吗?

{
    name: "Item A",
    subItems: [{
        name: "Subitem 1",
        value: 10
    },
    {
        name: "Subitem 2",
        value: 20
    }]
},
{
    name: "Item B",
    subItems: [{
        name: "Subitem 1",
        value: 5
    },
    {
        name: "Subitem 2",
        value: 60
    }]
}

我想按其中一个子项的值对文档进行排序,以便按升序排序的预期结果低于(在这种情况下,按降序排序也会给出相同的结果,因为项目 B 具有最低和最大价值的项目)。我并不关心这个查询中子项的顺序,只关心父文档的顺序。

预期结果:

{
    name: "Item B",
    subItems: [{
        name: "Subitem 1",
        value: 5
    },
    {
        name: "Subitem 2",
        value: 60
    }]
},
{
    name: "Item A",
    subItems: [{
        name: "Subitem 1",
        value: 10
    },
    {
        name: "Subitem 2",
        value: 20
    }]
}

我知道它必须使用聚合,但不知道如何开始。任何帮助表示赞赏。

【问题讨论】:

    标签: database mongodb mongodb-query aggregation-framework


    【解决方案1】:

    取决于您所谈论的价值。

    场景 1

    如果按数组本身排序,则在升序/降序排序时,它将使用最小值/最大值。只需这样做:

    db.coll.find({...}).sort({"subItems.value"})
    

    没有任何索引可以支持这种排序。

    场景 2

    或者,您可以指定要用作排序键的元素:

    db.coll.find({...}).sort({"subItems.0.value"})
    

    这种排序可以支持:

    db.coll.createIndex({"subItems.0.value": 1})
    

    场景 3

    如果以上都不是您想要的,我想您可能是指按某些条件过滤并按该元素排序。这可以通过使用聚合来实现:

    db.bar.aggregate([
        {$match: {"subItems.value": {$lte: 10}}}, 
        {$project: {
            subItems: {
                $filter: {
                    input: "$subItems",
                    as: "item",
                    cond: {
                        $lte: ["$$item.value", 10]
                    }
                }
            }
        }},
        {$sort: {"subItems.value": -1}}
    ])
    

    $filter 运算符本质上是通过某些条件过滤元素。之后,这与我们在场景 1 中所做的按数组排序没有什么不同。
    在此查询中,第一个 $match 可以利用索引 {"subItems.value": 1},而 $project$sort 是纯 CPU 工作。

    【讨论】:

    • “场景”中没有一个是正确的。 OP 需要 $sort 数组内的最小值。
    【解决方案2】:

    您可以在这里使用最简单的解决方案。

    使用$min 聚合运算符查找subItems 数组中的最小值,然后使用$sort 来查找

    db.collection.aggregate([
      { "$addFields": {
        "order": { "$min": "$subItems.value" }
      }},
      { "$sort": { "order": 1 }}
    ])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-28
      • 2021-01-03
      • 2011-09-01
      • 2021-04-10
      • 2021-12-27
      相关资源
      最近更新 更多