在数组mongodb

时间:2018-12-28 01:11:15

标签: database mongodb mongodb-query aggregation-framework

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

{
    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
    }]
}

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

2 个答案:

答案 0 :(得分:0)

取决于您在说什么值。

场景1

如果按数组本身进行排序,则在您按升序/降序排序时将使用最小值/最大值。只需:

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

任何索引都无法支持这种排序。

场景2

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

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

可以通过以下方式支持这种排序:

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

场景3

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

$match

$filter运算符实际上是根据某种条件过滤元素的。之后,就像在场景1中按数组排序一样。
在此查询中,第一个{"subItems.value": 1}可以利用索引$project,而$sort和{{1}}是纯CPU工作。

答案 1 :(得分:0)

这里有最简单的解决方案。

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

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