【问题标题】:Mongodb: Querying array of subdocumentsMongodb:查询子文档数组
【发布时间】:2014-12-11 18:35:42
【问题描述】:

我有用户的集合,其架构如下:

{
  _id: unique number,
  name: 'asdf',
  age: '12',
  gender: 'm',
  address: [
    {area: 'sdf',
     city: 'sdq', 
     state: 'wfw'},
    {area: 'asdf',
     city: 'sdfs',
     state: 'vfdwd'}
  ]
}

我想找出stateaddress 中的所有值应该是我传递的值的用户。如果 state 值之一与我传递的值不匹配,则不应返回用户。 我尝试使用$unwind$match 进行简单的查找、聚合框架,但似乎没有任何解决方案。你能帮帮我吗...

谢谢

附:为了提问,请忍受多个地址。 :)

【问题讨论】:

  • 您可以粘贴您的文档吗?

标签: arrays mongodb subdocument


【解决方案1】:

要确定所有数组条目是否与状态“wfw”匹配,请执行如下聚合:

db.users.aggregate([
    { "$project" : {
        "test" : {
            "$allElementsTrue" : [{
                "$map" : { 
                    "input" : "$address", 
                    "as" : "a", 
                    "in" : { "$eq" : ["wfw", "$$a.state"] }
                }
            }]
        }
    } },
    { "$match" : { "test" : true } }
])

这个聚合取每个文档,将“state equals 'wfw'”映射到地址数组上得到一个布尔数组,并测试整个数组是否为真,将结果存储在`test中,然后根据过滤结果测试。您将需要 MongoDB 2.6 来支持某些运算符。

【讨论】:

  • $all 有什么不同?
  • $all 检查 $all 的数组参数的所有元素是否存在于数组字段中,而不是数组字段的所有元素都在数组参数的元素中$all。例如,{ "$all" : [1, 2, 3] } 匹配 [1, 2, 3, 4],而不是 [1, 2]。这不是 OP 需要的。
  • 嗨 wdberkeley。感谢您的解决方案。我试过了,但它显示以下异常。你能弄清楚为什么 - 失败:异常:$allElementsTrue 的参数必须是一个数组,但是是 NULL
  • 我还有一个疑问:我们可以在聚合中有多个 $match 阶段吗?我有这种情况,一个查询的结果应该被转发到下一个查询等等(因为查询是优先的)并且这些查询本质上是比较的。聚合框架似乎是此类问题的最佳解决方案(因为管道)。但是,如果您有任何其他方式可以提出建议,我将不胜感激。
  • 是的,您可以拥有多个$match 阶段。如果可能的话,最好压缩成一个查询,我会说,因为只有第一个匹配项才能使用索引。
【解决方案2】:

我不知道我是否理解。

我复制了您的文档。当您想通过state 检索用户时,您可以通过多种方式进行

如果你用单个值搜索,你可以这样做

db.g.find({ "address.state": "wfw" })

并检索用户

你可以使用$all

db.g.find( { "address.state": { $all: ["wfw","vfdwd"] } } ) // retrieve User

db.g.find( { "address.state": { $all: ["wfw","vfdwd","foo"] } } ) // don't retrieve User

或者你可以使用$and

db.g.find( { $and: [ { "address.state":"wfw" },{ "address.state":"vfdwd" }] } )

但我不知道我是否理解你的问题

更新和正确答案

db.g.find( { "address.state": { $nin: ["wfw"] } } )

告诉我

【讨论】:

  • 嗨,巴诺。这是我尝试过的。但它似乎没有给我想要的解决方案。无论如何感谢您的帮助。关于这个问题,我想检索没有任何与我传递的值匹配的状态地址的用户。例如,尚未处于“wfw”状态的用户。在这种情况下,查询应该返回没有任何与“wfw”匹配的州地址的用户。明白了吗?
  • @harshad 也许现在我明白了。 db.g.find( { "address.state": { $nin: ["wfw"] } } ) 之类的东西?
  • 非常感谢巴诺。你说对了!它似乎工作。得到了解脱。 :)
猜你喜欢
  • 2016-09-29
  • 2019-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多