【问题标题】:Filter the returned elements in an array after a mongodb querymongodb查询后过滤数组中返回的元素
【发布时间】:2015-04-23 12:06:49
【问题描述】:

如果我理解正确,这在 mongodb 中称为 projection。我已经看到有两种有用的投影运算符:elemMatch$

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

现在,当文档与查询匹配时,Java 驱动程序将返回整个文档。我想对其进行过滤以仅返回与原始查询匹配的属性。

我尝试过结合elemMatch,但我所能完成的只是返回所有属性或仅返回一个(通常是第一个匹配项)。

Mongo 文档结构如下:

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

我的查询为:

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

它返回以下结果:

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

示例和返回的是不同的文档。虽然我匹配了two 属性,但我得到了整个列表。

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

我怎样才能做到这一点?

编辑:

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

【问题讨论】:

  • 您能给我们展示一些示例文档,您尝试过的代码和预期的结果吗?
  • @chridam 完成。如果还有什么需要请说。
  • @Saraiva $elemMatch 有这样的限制,它只返回匹配$elemMatch 条件的第一个元素,如果你运行这个查询{"attributes":{"$elemMatch":{"tag":"media"}},"attributes":{"$elemMatch":{"tag":"teste"}}},{"attributes.$.tag":1} 它只返回一个匹配数组而不是整个数组,所以如果你想找出所有匹配的数组然后应该使用 mongo 聚合
  • @yogesh 我了解如何通过使用 unwind 等技术获得它。但是,我不控制查询。我试图找到一种方法,以某种方式了解哪些属性成功匹配,而无需对查询内容有任何先验知识。我还没有找到可以做到这一点的聚合。我可以详细说明为什么我认为聚合可能不起作用..

标签: java mongodb mongodb-query mongodb-java


【解决方案1】:

假设您要匹配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()

【讨论】:

  • 非常感谢您的帮助。我意识到我必须限制查询输入并做类似的事情。后来生病更新了完整的解决方案和描述。
【解决方案2】:

找到可能的解决方案:Solution A

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

【讨论】:

  • 据我了解,我认为您想在展开时匹配两个标签,例如 tag:mediatag:stream ?你不能写聚合查询吧?
  • @yogesh 从一个未知的查询(不是我创建的)我想,以防文档匹配,知道哪些已注册的属性给出了正匹配。例如,如果我有一个包含 10 个属性的文档和一个匹配 7 个属性的查询。我希望查询返回只有 7 个匹配属性的完整文档。因此,这是一个过滤数组的情况。
猜你喜欢
  • 1970-01-01
  • 2021-12-28
  • 2019-06-22
  • 2015-05-22
  • 1970-01-01
  • 2021-12-28
  • 2015-04-25
  • 1970-01-01
相关资源
最近更新 更多