如何对嵌套在另一个数组中的数组中的字段执行查找?

问题描述 投票:0回答:1

我有一个 mongo 集合(表),其中包含以下形式的文档:

{
  "tableName": "Items",
  "rows": [
    {
      "label": "row 1 label here",
      "items": ["item1", "item2", "item3"]
    },
    {
      "label": "row 2 label here",
      "items": ["item4", "item5", "item6"]
    }
  ]
}

我还有另一个集合(项目),其中包含以下形式的文档:

{
  "id": "item1",
  "name": "Item name",
  "code": "XXX-XXXX-XXXX",
  "price": 100
}

现在我想查询给定表中的所有项目,因此我使用以下聚合:

{
  "$lookup": {
    from: "items",
    localField: "rows.items",
    foreignField: "id",
    as: "rows.items"
  }
}

所以我希望所有的“item1”,“item2”,...都被替换为相应的文档:

{
  "tableName": "Items",
  "rows": [
    {
      "label": "row 1 label here",
      "items": [
        {
          "id": "item1",
          "name": "Item name",
          "code": "XXX-XXXX-XXXX",
          "price": 100
        },
        ... // the rest of the items
      ]
    },
    ... // the rest of the rows
  ]
}

但是,“rows”作为对象返回,仅包含预期数组中的第一个对象,并且标签字段甚至消失了:

{
  "tableName": "Items",
  "rows": { // <-- rows is returned as on object, should be array
    "items": [  // <-- the "label" field is missing
      {
        "id": "item1",
        "name": "Item name",
        "code": "XXX-XXXX-XXXX",
        "price": 100
      },
      ... // the rest of the items
    ]
  }
}

那么如何保留外部数组和缺失的字段?

mongodb mongoose
1个回答
0
投票

这就是我个人反对使用嵌套数组的原因。它给查询带来了不必要的复杂性。

您可能需要在

$unwind
rows
级别上
rows.items
两次才能展平阵列。使用查找结果执行
$lookup
$mergeObjects
。然后,您需要执行 2
$group
才能恢复到原始结构。

db.tables.aggregate([
  {
    "$unwind": "$rows"
  },
  {
    "$unwind": "$rows.items"
  },
  {
    "$lookup": {
      "from": "items",
      "localField": "rows.items",
      "foreignField": "id",
      "as": "itemsLookup"
    }
  },
  {
    "$unwind": "$itemsLookup"
  },
  {
    "$set": {
      "rows": {
        "$mergeObjects": [
          "$rows",
          "$itemsLookup"
        ]
      }
    }
  },
  {
    "$group": {
      "_id": {
        "_id": "$_id",
        "label": "$rows.label"
      },
      "tableName": {
        "$first": "$tableName"
      },
      "rows": {
        "$push": "$rows"
      }
    }
  },
  {
    "$group": {
      "_id": "$_id._id",
      "tableName": {
        "$first": "$tableName"
      },
      "rows": {
        "$push": {
          "label": "$_id.label",
          "items": "$rows"
        }
      }
    }
  }
])

蒙戈游乐场


如果您发现自己经常在

rows.items
级别工作,请考虑重构架构以将条目存储为单独的文档,例如 this。您也可以通过索引获得潜在的性能提升。

© www.soinside.com 2019 - 2024. All rights reserved.