【问题标题】:How should I find a Mongoose subdocument given the parent document and a value in the subdocument?给定父文档和子文档中的值,我应该如何找到 Mongoose 子文档?
【发布时间】:2015-04-04 22:19:40
【问题描述】:

我只是试图做一个类似于.findOne 的基本查找,但是在 Mongoose 的一个子文档数组上。我应该简单地遍历数组以寻找正确的子文档吗?

我有这样的架构:

var RegionSchema = new Schema({
  "metadata": {
    "regionType": String,
    "name": String,
    "children": [{
      "name": String,
      "childType": String
    }],
    "parent": Schema.ObjectId
  },

  "data": [DataContainer]
});

我知道我想在data 中找到一个DataContainer,其中dataYear 等于"2014"。我是 MongoDB 新手,所以我不知道很多高级命令。什么是最有效的方法?

编辑:dataYear 保证在该数组中是唯一的。

【问题讨论】:

  • 您能否同时显示DataContainer 架构以及包含数据的示例文档?
  • 这很简单。对于这个问题,DataContainer 包含population(数字)和dataYear(字符串)。 dataYear 对数组中的每个子文档都是唯一的。所以这不是一个大查询。
  • @Antrikshy 你检查过建议的答案了吗?
  • 我最终做了其他事情。因为我处理的是较小的数组,所以我创建了一个函数,它只通过并返回我试图找到的子文档的索引。

标签: node.js mongodb mongoose


【解决方案1】:

为此使用聚合框架。您的聚合管道将包含一个 $match 操作阶段,它匹配集合中的文档,其中数据数组元素对象的字段 dataYear 的值等于 "2014"。下一个流水线阶段将是对数据数组对象的$unwind 操作和另一个用于过滤数组的$match 流水线。最后阶段将是$project 解构数组。例如,假设您有一个使用RegionSchema 的模型Region,您的猫鼬代码将是:

Region.aggregate([
    // similar query object you use in findOne() can also be applied to the $match
    {
        "$match": {
            "data.dataYear": "2014",
            "metadata.name": "example text" 
        }        
    },
    {
        "$unwind": "$data"
    },
    {
        "$match": {
            "data.dataYear": "2014"
        }        
    },
    {
        "$project": {
            "_id": 0,
            "dataYear": "$data.dataYear",
            "population": "$data.population"
        }        
    }
], function(err, docs){

});

【讨论】:

  • 但是我已经使用findOne 获得了一个Region 文档,我只想在data 中找到那个年份的子文档。可能还有其他Regions 和data.dataYear == "2014",但我只想看看这个数组里面。
  • @Antrikshy 您在Region.findOne({query}) 中使用的查询对象也适用于使用第一个$match 操作管道阶段的聚合。试试看,这将为您提供所需的子文档。如果它不适合你,请告诉我。
【解决方案2】:

您可以在查询中添加$elemMatch

假设Region是模型:

Region.findOne(...).select({data: {$elemMatch: {dataYear: 2014}});

这将返回 Region 文档,其中 data 数组仅包含匹配项。

更新:如果您已经有一个包含子文档数组的文档,您可以使用类似 lodash 的 find 方法来选择子文档。注意:这会将子文档转换为 POJO。

_.find(region.data.toObject(), {dataYear: 2014});

【讨论】:

  • 我说我有父文档,只需要在这个父文档里面找一个子文档。
  • 所以你还想要整个数组吗?抱歉,您最初的问题并不清楚。 Mongoose 对子文档的唯一匹配方法是 [id]() 方法,该方法仅在您知道子文档的 id 时才有用。由于您正在使用另一个字段进行匹配,因此您必须使用外部解决方案来执行此操作。更新我的答案以显示示例。
猜你喜欢
  • 2014-02-04
  • 2013-03-19
  • 1970-01-01
  • 2020-07-16
  • 2021-04-04
  • 2016-03-24
  • 2015-02-10
  • 1970-01-01
  • 2016-07-30
相关资源
最近更新 更多