【问题标题】:MongoDB: match non-empty doc in arrayMongoDB:匹配数组中的非空文档
【发布时间】:2011-07-07 07:12:06
【问题描述】:

我有一个这样构成的集合:

{
  _id: 1,
  score: [
    {
      foo: 'a',
      bar: 0,
      user: {user1: 0, user2: 7}
    }
  ]
}

我需要找到至少有一个“分数”(分数数组中的元素)的所有文档,该“分数”具有一定的“bar”值和一个非空的“用户”子文档。

这就是我想出的(而且看起来应该可行):

db.col.find({score: {"$elemMatch": {bar:0, user: {"$not":{}} }}})

但是,我得到了这个错误:

error: { "$err" : "$not cannot be empty", "code" : 13030 }

还有其他方法吗?

【问题讨论】:

  • 确实是这样的结构吗?好像有点不对劲> var doc = { score: [ foo: 'a', bar: 0, user: { user1: 0, user2: 7 } ] }; Thu Jul 7 00:43:42 SyntaxError: missing ] after element list (shell):1
  • @Justin:你说得对,忘记了数组中的大括号。

标签: mongodb nosql


【解决方案1】:

想通了:{ 'score.user': { "$gt": {} } } 将匹配非空文档。

【讨论】:

  • 在这种情况下,score.user 是一个对象。检查数组score是否为空也可以吗?
  • 可能,但对于数组,您可能最好使用:{ foo: { $not: { $size: 0 } } }
  • 太棒了!我测试了,两者都有效。你知道为什么第二种选择会更好吗?
  • @knoxxs:请参阅排序顺序的文档:docs.mongodb.org/manual/reference/bson-types - 空文档在任何非空文档之前排序,但 null 将在任何(包括空)文档之前排序。
【解决方案2】:

我不确定我是否完全理解您的架构,但也许最直接的方法是不要为 score.user 设置“空”值?

如果没有内容,则故意在您的文档中包含该字段?

那么您的查询可能类似于...

> db.test.find({ "score" : { "$elemMatch" : { bar : 0, "user" : {"$exists": true }}}})

即在 score.bar 中查找您想要的值(在本例中为 0)检查 score.user(如果它有值,那么它就会存在?)

已编辑:哎呀,我错过了你的 $elemMatch ...

【讨论】:

  • 是的,我想过这样做,我更喜欢既不存在又匹配空user的查询的主要原因是可以删除单个用户的分数,我'宁愿不用每次都检查子文档是否为空,是否需要删除。
【解决方案3】:

您可能想要添加一个辅助数组来跟踪user 文档中的用户:

{
  _id: 1,
  score: [
    {
      foo: 'a',
      bar: 0,
      users: ["user1", "user2"],
      user: {user1: 0, user2: 7}
    }
  ]
}

然后你可以原子地添加新用户:

> db.test.update({_id: 1, score: { $elemMatch: {bar: 0}}},                       
... {$set: {'score.$.user.user3': 10}, $addToSet: {'score.$.users': "user3"}})

删除用户:

> db.test.update({_id: 1, score: { $elemMatch: {bar: 0}}},
... {$unset: {'score.$.user.user3': 1}, $pop: {'score.$.users': "user3"}})      

查询分数:

> db.test.find({_id: 1, score: {$elemMatch: {bar: 0, users: {$not: {$size: 0}}}}})

如果您知道您只会添加不存在的用户并从user 文档中删除存在的用户,您可以将users 简化为一个计数器而不是一个数组,但上面的方法更有弹性。

【讨论】:

    【解决方案4】:

    查看 $size 运算符以检查数组大小。

    【讨论】:

    • 我没有检查任何数组的大小。我之前遗漏了一组牙套,现在可能更清楚了。文档/对象的等效运算符可以工作,但似乎不存在。
    猜你喜欢
    • 2019-09-03
    • 1970-01-01
    • 2021-05-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-17
    • 1970-01-01
    • 2013-03-28
    • 2017-05-18
    相关资源
    最近更新 更多