用$ where查询子数组

时间:2013-07-27 04:08:04

标签: mongodb mongomapper mongodb-php mongodb-java

我有一个包含以下文档的集合:

{
"_id" : ObjectId("51f1fd2b8188d3117c6da352"),
"cust_id" : "abc1234",
"ord_date" : ISODate("2012-10-03T18:30:00Z"),
"status" : "A",
"price" : 27,
"items" : [{
  "sku" : "mmm",
  "qty" : 5,
  "price" : 2.5
}, {
  "sku" : "nnn",
  "qty" : 5,
  "price" : 2.5
}]
}

我想在“items”的字段中使用“$ where”,所以某事就像这样:

{$where:"this.items.sku==mmm"} 

我该怎么办?当字段不是数组类型时,它可以工作。

3 个答案:

答案 0 :(得分:2)

您不需要$where运算符来执行此操作;只需使用以下查询对象:

{ "items.sku": mmm }

至于你的$where无效的原因,该运算符的值是作为JavaScript执行的,因此不会检查items数组的每个元素,它只会处理{ {1}}作为普通对象,并将其items属性(未定义)与sku进行比较。

答案 1 :(得分:0)

您正在将this.items.sku与变量mmm进行比较,该变量未初始化,因此值为unefined。你想要做的是迭代数组并将每个条目与字符串'mmm'进行比较。此示例通过使用返回true的数组方法some来完成此操作,当传递的函数返回true时,至少有一个条目:

{$where:"return this.items.some(function(entry){return entry.sku =='mmm'})"} 

但实际上,不要这样做。在JohnnyHK对答案的评论中,你说“我的服务只是用户和mongodb之间的接口,完全不知道现场客户想要存储的内容”。你并没有真正解释你的用例,但我相信你可以更好地解决这个问题。

  • 即使这样,$ where运算符也会调用Javascript引擎 可以使用普通查询完成普通表达式。这意味着不必要的性能开销。
  • 集合中的每个文档都会传递给函数,因此当您有索引时,它就无法使用。
  • 当javascript函数是从客户端提供的东西生成的时候,你必须小心谨慎并正确地转义它,否则你的应用程序容易受到代码注入的攻击。

答案 2 :(得分:0)

除了问题之外,我一直在阅读你的评论。听起来您的用户可以通常添加一些属性,这些属性存储在文档中的数组中。您的客户端需要能够以通用方式从文档中查询任意对。实现这一目标的模式通常如下:

 {
    .
    .
    attributes:[
     {k:"some user defined key",
      v:"the value"},
     {k: ,v:}
      .
      .
    ]
 }

请注意,在您的情况下,项目是属性。现在要获取文档,您的查询将类似于:

eg)
db.collection.find({attributes:{$elemMatch:{k:"sku",v:"mmm"}}});
(index attributes.k, attributes.v)

这允许您的服务提供一种查询数据的方法,并让客户端指定k,v对的内容。这个设计的一个警告是始终要知道文档有16MB的限制(除非你有一个使GridFS合适的用例)。像$ slice这样的函数可以帮助控制它。