我有一个包含以下文档的集合:
{
"_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"}
我该怎么办?当字段不是数组类型时,它可以工作。
答案 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之间的接口,完全不知道现场客户想要存储的内容”。你并没有真正解释你的用例,但我相信你可以更好地解决这个问题。
答案 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这样的函数可以帮助控制它。