仅从对象猫鼬数组返回匹配项

时间:2020-07-18 15:53:19

标签: mongodb mongoose mongodb-query

[
  {
    item: "journal",
    instock: [
      {
        warehouse: "A",
        qty: 5,
        items: null
      },
      {
        warehouse: "C",
        qty: 15,
        items: [
          {
            name: "alexa",
            age: 26
          },
          {
            name: "Shawn",
            age: 26
          }
        ]
      }
    ]
  }
]
db.collection.find({
  "instock.items": {
    $elemMatch: {
      name: "alexa"
    }
  }
})

这将返回整个items数组,因为我只想要带有一个项{name:'alexa',age:26}的items数组

游乐场链接:https://mongoplayground.net/p/0gB4hNswA6U

3 个答案:

答案 0 :(得分:2)

您可以使用.aggregate(pipeline)函数。

您的代码如下:

db.collection.aggregate([{
    $unwind: {
        path: "$instock"
    }
}, {
    $unwind: {
        path: "$instock.items"
    }
}, {
    $replaceRoot: {
        newRoot: "$instock.items"
    }
}, {
    $match: {
        name: "alexa"
    }
}])

此管道中使用的命令:

$ unwind -将项目数组解构为多个文档,这些文档都包含原始文档的原始字段,但展开的字段现在具有数组中所有解构对象的值。

$ replaceRoot -获取newRoot上引用的内部对象,并将其作为文档。

$ match -一种通过某种条件过滤最终生成的文档列表的方法。基本上是.find()函数中的第一个参数。

有关聚合的更多信息,请访问MongoDB的网站:

编辑

所需的结果是获取单个项目数组作为响应,以实现只需删除管道中的$replaceRoot阶段即可。

最终管道:

db.collection.aggregate([{
    $unwind: {
        path: "$instock"
    }
}, {
    $unwind: {
        path: "$instock.items"
    }
}, {
    $match: {
        "instock.items.name": "alexa"
    }
}])

答案 1 :(得分:1)

一种替代方法,其中$filter是项目阶段的关键。

db.collection.aggregate([
  {
    $match: {
      "instock.items.name": "alexa"
    }
  },
  {
    $unwind: "$instock"
  },
  {
    $project: {
      "item": "$item",
      qty: "$instock.qty",
      warehouse: "$instock.warehouse",
      items: {
        $filter: {
          input: "$instock.items",
          as: "item",
          cond: {
            $eq: [
              "$$item.name",
              "alexa"
            ]
          }
        }
      }
    }
  },
  {
    $group: {
      _id: "$_id",
      instock: {
        $push: "$$ROOT"
      }
    }
  }
])

想法是:

  • 已将$match作为顶级过滤器
  • 然后$unwind instock个数组项来准备$filter
  • 使用$project保留其余字段,并在$filter数组字段上使用items
  • 最后一次归因于$group,因为先前使用过$unwind

Play link

答案 2 :(得分:0)

您必须在投影部分使用$elemMatch

db.collection.find({
  // whatever your query is
}, {
  "instock.items": {
    $elemMatch: {
      name: "alexa"
    }
  }
});

更新

Here是这种用法的一个很好的例子。摘自mongodb官方文档。