0

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

{
"_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"} 

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

4

3 回答 3

2

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

{ "items.sku": mmm }

至于你为什么$where不工作,该运算符的值作为 JavaScript 执行,因此不会检查items数组的每个元素,它只是将其items视为普通对象并将其sku属性(未定义)与mmm.

于 2013-07-27T04:20:50.920 回答
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 这样的函数可以帮助控制它。

于 2013-07-27T19:48:50.687 回答
0

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

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

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

  • $where 运算符调用 Javascript 引擎,即使这个简单的表达式可以通过普通查询完成。这意味着不必要的性能开销。
  • 集合中的每一个文档都被传递给函数,所以当你有索引时,它不能被使用。
  • 当从客户端提供的东西生成 javascript 函数时,您必须小心正确地对其进行清理和转义,否则您的应用程序容易受到代码注入的攻击。
于 2013-07-27T05:26:32.143 回答