在 mongodb 查询后过滤数组中返回的元素

Filter the returned elements in an array after a mongodb query

如果我没理解错的话,这在mongodb中叫做projection。我看到有两种有用的投影运算符:elemMatch$.

我有一组文档,每个文档都有一个属性列表(对象)。我想执行复杂的查询来匹配这些属性,即匹配它的几个字段(使用 regex,等等)。

现在,当文档与查询匹配时,Java 驱动程序正在 return 处理整个文档。我想将其过滤为 return 与原始查询匹配的属性。

我已经尝试组合 elemMatch 但我所能完成的只是 return 所有属性或只有一个(通常是第一个匹配项)。

Mongo 文档结构如下:

    {
    "name": "MediaPlayer",
    "attributes": [
        {
            "tag": "media",
            "values": [
                "mp3",
                "mp4"
            ]
        },
        {
            "tag": "teste",
            "values": [
                "teste"
            ]
        }
    ]
}

我的查询是:

{attributes : {$elemMatch: { 'tag' : 'media'},$elemMatch: { 'tag' : 'stream'}}}

它 return 以下结果:

{
    "name": "MediaStream",
    "attributes": [
        {
            "tag": "media",
            "values": [
                "Edit"
            ]
        },
        {
            "tag": "stream",
            "values": [
                "Edit"
            ]
        },
        {
            "tag": "video",
            "values": [
                "Edit"
            ]
        }
    ]
}

示例和returned 是不同的文档。尽管我匹配了 two 个属性,但我得到了整个列表 returned。

我希望属性数组只包含匹配的元素。

我怎样才能做到这一点?

编辑:

据我所知,mongodb 查找操作不支持内部数组过滤。有一些使用 mongodb 聚合框架的例子。除此之外,手动过滤似乎是唯一可能的方法。

找到可能的解决方案:

编辑:找到的聚合并不能证明提供了问题的通用解决方案,因为我没有控制查询。从这个意义上说,如果我想展开属性,然后将其与查询进行匹配,它将仅适用于匹配单个属性的查询。

假设您要匹配 tag:mediatag:stream,这种情况下您在 mongo $in 聚合查询中输入了如下匹配条件

db.collectionName.aggregate({
"$unwind": "$attributes" // first unwind attributes array 
}, {
"$match": {
  "attributes.tag": {
    "$in": ["media", "stream"] // put all matching tags in array using $in
  }
}
}, {
"$group": {
  "_id": "$_id",
  "name": {
    "$first": "$name"
  },
  "attributes": {
    "$push": "$attributes" // push all attributes to get only matching tags
  }
}
}).pretty()