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

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

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

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

但是,"row"作为对象返回,只包含预期数组中的第一个对象,标签字段甚至不见了:

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

Edit:以下分别是"行"、"项"和"表"的模式:

const RowSchema = new Schema({
  label: String,
  items: [String]
}, {
  _id: false
})

const ItemSchema = new Schema({
  id: String,
  name: String,
  code: String,
  price: Number
}, {
  _id: false
})

const TableSchema = new Schema({
  tableName: String,
  rows: [RowSchema]
})

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

推荐答案

另一种 Select 是避免返回$unwind$group,代之以$reduce$map:

db.tables.aggregate([
  {$set: {items: {$reduce: {
          input: "$rows",
          initialValue: [],
          in: {$concatArrays: ["$$value", "$$this.items"]}
  }}}},
  {$lookup: {
      from: "items",
      localField: "rows.items",
      foreignField: "id",
      as: "itemsLookup"
  }},
  {$set: {
      rows: {$map: {
          input: "$rows",
          as: "row",
          in: {$mergeObjects: [
              "$$row",
              {items: {$map: {
                    input: "$$row.items",
                    as: "item",
                    in: {
                      $arrayElemAt: [
                        "$itemsLookup",
                        {$indexOfArray: ["$itemsLookup.id", "$$item"]}
                      ]
                  }
              }}}
          ]}
      }},
      itemsLookup: "$$REMOVE",
      items: "$$REMOVE"
  }}
])

看看它在playground example米上是如何工作的

  • 我同意@ray的建议,根据您的需求重新考虑您的模式

Mongodb相关问答推荐

MongoDB合并按键更新值的对象数组

在MongoDB中获取所有帖子时如何获取相关用户信息

为什么 mongoose 在 mongodb 中找不到我的数据

如何在 MongoDB 中的集合下查找同一文档

spring-data-mongodb 上的 TopN 聚合

判断对象数组中的值是否存在golang

从 kubectl exec 获取返回值到 powershell 脚本

TypeError:Cannot read property '_id' of undefined

将 MongoDB BsonDocument 转换为字符串

mongoose中的 required是什么意思?

如何构建我只需要打开一次 mongodb 连接的快速应用程序?

使用 nodejs/mongoose 部分更新子文档

在 URL 中使用 ID(来自 mongo 的 ObjectId)是否安全?

如何使用 java 驱动程序更新 mongo db 中的文档字段?

为什么使用 Redis 而不是 MongoDb 进行缓存?

查询 Mongoid/rails 3 中的嵌入对象(Lower than、Min 运算符和排序)

120 个 mongodb 集合与单个集合 - 哪个更有效?

MongoError:failed to connect to server [localhost:27017] on first connect

在 NodeJs 中处理 Mongodb 全局连接的最佳方法是什么

哪个数据库适合我的应用程序 mysql 或 mongodb ?使用 Node.js 、 Backbone 、 Now.js