简体   繁体   English

如何从嵌套数组 mongodb 中获取单个匹配的文档?

[英]How to fetch single matched document from nested array mongodb?

I have nested array object in my MongoDB document, but the predicate is not return as expected, which in this case I only want matched document only.我在我的 MongoDB 文档中嵌套了数组 object ,但是谓词没有按预期返回,在这种情况下我只想要匹配的文档。

Document Structure文件结构

{
"_id": {
    "$oid": "5fddb34848be35283c36955b"
},
"projectId": {
    "$oid": "5fddb30d48be35283c36955a"
},
"urls": [
    {
        "_id": {
            "$oid": "5fddb34848be35283c36955c"
        },
        "group": "User",
        "data": [
            {
                "option": {
                    "applyDifferentContentType": false,
                    "allowInjection": false
                },
                "_id": {
                    "$oid": "5fddad1e48be35283c369558"
                },
                "url": "/users/create",
                "method": "patch",
                "headers": {
                    "Content-Type": "multipart/form-data"
                }
            },
            {
                "option": {
                    "applyDifferentContentType": false,
                    "allowInjection": false
                },
                "_id": {
                    "$oid": "5fddad1e48be35283c369558"
                },
                "url": "/users/update",
                "method": "post",
                "headers": {
                    "Content-Type": "application/json"
                }
            },
            {
                "option": {
                    "applyDifferentContentType": false,
                    "allowInjection": false
                },
                "_id": {
                    "$oid": "5fddad1e48be35283c369558"
                },
                "url": "/users/delete",
                "method": "post",
                "headers": {
                    "Content-Type": "application/json"
                }
            }
        ]
    },
    {
        "_id": {
            "$oid": "5fddb34f48be35283c36955d"
        },
        "group": "Project",
        "data": [
            {
                "option": {
                    "applyDifferentContentType": true,
                    "allowInjection": false
                },
                "_id": {
                    "$oid": "5fddad1e48be35283c369558"
                },
                "url": "/project/create",
                "method": "post",
                "headers": {
                    "Content-Type": "application/json"
                }
            },
            {
                "option": {
                    "applyDifferentContentType": false,
                    "allowInjection": false
                },
                "_id": {
                    "$oid": "5fddad1e48be35283c369558"
                },
                "url": "/projects/update",
                "method": "post",
                "headers": {
                    "Content-Type": "application/url-encoded"
                }
            }
        ]
    },
    {
        "_id": {
            "$oid": "5fddb37d48be35283c36955e"
        },
        "group": "Contact",
        "data": [
            {
                "option": {
                    "applyDifferentContentType": false,
                    "allowInjection": false
                },
                "_id": {
                    "$oid": "5fddad1e48be35283c369558"
                },
                "url": "/contact/create",
                "method": "post",
                "headers": {
                    "Content-Type": "multipart/form-data"
                }
            }
        ]
    }
],
"__v": 0 }

Fetch Query获取查询

const result = await URLPayload.find({ 
  "projectId": projectId,
  "urls.data": {
    $elemMatch: {
      "_id": dataId
    }
  }
})
.lean();

projectId => 5fddb30d48be35283c36955a
dataId => 5fddad1e48be35283c369558

But above predicate is not giving expected result.但是上面的谓词没有给出预期的结果。 How to return only matched single document from nested array object?如何从嵌套数组 object 中仅返回匹配的单个文档?

I have nested array object in my MongoDB document, but the predicate is not return as expected, which in this case I only want matched document only.我在我的 MongoDB 文档中嵌套了数组 object ,但是谓词没有按预期返回,在这种情况下我只想要匹配的文档。

I'm not used working with $oid inside the _id element but this should work.我不习惯在 _id 元素中使用 $oid ,但这应该可以。

    const ids = {
        projectId: "5fddb30d48be35283c36955a",
        urlId: "5fddb34848be35283c36955c",
        dataId: "5fddad1e48be35283c369558"
    }

    await URLPayload.findOne({ "projectId.$oid": ids.projectId },
        {
            "$elemMatch": { "urls.$[url].data": { "_id.$oid": ids.dataId } }
        }, {
        "arrayFilters": [
            { "url._id.$oid": ids.urlId }
        ]
    }, (err, urlPayloadResult) => {
        if (err) {
            console.log(err)
        } else {
            console.log({ message: urlPayloadResult })
        }
    })

If not work in your case just remove the ".$oid" element.如果在您的情况下不起作用,只需删除“.$oid”元素。

Let me know if this work.让我知道这是否有效。

You can use aggregation pipeline,您可以使用聚合管道,

  • make your you have to convert projectId and dataId input fields string type to object type using mongoose.Types.ObjectId使您必须使用mongoose.Types.ObjectIdprojectIddataId输入字段字符串类型转换为 object 类型
  • $match your conditions, $match您的条件,
  • $project to show required documents $project显示所需文件
  • $reduce to iterate loop of urls array $reduce迭代urls数组的循环
  • $filter to iterate loop of urls.data array and filter matching _id , $filter迭代urls.data数组的循环并过滤匹配_id
  • $first will return object from the array, you can use $arrayElemAt instead of $first for older version of MongoDB $first将从数组中返回 object,对于旧版本的 MongoDB,您可以使用$arrayElemAt而不是$first
const result = await URLPayload.aggregate([
  {
    $match: {
      projectId: mongoose.Types.ObjectId(projectId),
      "urls.data._id": mongoose.Types.ObjectId(dataId)
    }
  },
  {
    $project: {
      urlData: {
        $reduce: {
          input: "$urls",
          initialValue: {},
          in: {
            $first: {
              $filter: {
                input: "$$this.data",
                cond: { $eq: ["$$this._id", mongoose.Types.ObjectId(dataId)] }
              }
            }
          }
        }
      }
    }
  }
])

Playground操场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM