考虑到以下数据,我希望返回默认文档在MongoDB的数组字段中选择的结果。让我们调用集合books
。样本收集数据如下所示:
[
{
name: "Book1",
refs: [{ oid: "object1" }, { oid: "object2" }, {oid: "object5", default: true }]
},
{
name: "Book2",
refs: [{ oid: "object3" }, { oid: "object5", default: true }, { oid: "object7" }]
},
{
name: "Book3",
refs: [{ oid: "object4" }, { oid: "object2" }]
},
{
name: "Book4",
refs: [{ oid: "object5" }, { oid: "object4", default: true } ]
}
]
好吧。因此,为了简洁起见,很多关键值都在其中,但这并没有改变重点。
这里所需的逻辑如下:
refs
数组字段中查找并返回文档,该字段的默认值为true按照这一逻辑,我非常希望看到一些东西返回如下:
[
{
name: "Book1"
refs: [{oid: "object5", default: true }]
},
{
name: "Book2",
refs: [{ oid: "object5", default: true }]
},
{
name: "Book3",
refs: [{ oid: "object4" }]
},
{
name: "Book4",
refs: [{ oid: "object4" }]
}
]
现在我知道在聚合管道中有$cond操作符,但是这个条件的一部分似乎被绑定到在投影上获得一个$slice,其中default
属性在文档中不存在(并且可能被设置为true,但应该足够了)。
此逻辑模式基于使用$pull删除元素匹配的预期结果:
oid: "object5"
从每个文档数组中退出,然后仍然能够将返回到查询中数组的第一个元素。
因此,我正在寻找一些强 fu
,以便能够返回结果。
解决方案不能在主文档中添加另一个字段,引用数组文档中默认字段的值。实际上,没有这一点,所以$pull
操作在多点文档更新模式下工作。
编辑
这是作为一个查询,我的意思是当默认的属性没有设置时,我需要数组中的第一个元素,因为它是列出的。每次都是这样。
字符串是示例数据,因此不依赖词法顺序。在现实世界中,所有object#
引用都可能是真实的$oid。
这可能最终会成为赏金。如上所述,在允许更新的范围内接受架构更改。最糟糕的是,这些调查结果是JIRA问题的合理依据。
作为参考,我从我对这个职位的回答中提出了这一观点,这主要是关于重新思考模式以适应目标。
狩猎不错。
P.S和网秤,各位。对集合的更新需要在没有迭代的情况下进行,因为可能会有一个真的,真的,(哦,webscale!)很多人。
发布于 2014-02-03 12:11:45
下面是一个使用MongoDB 2.4.9中的聚合框架的示例,我认为它达到了您所追求的结果:
db.books.aggregate(
// Unwind the refs array
{ $unwind: "$refs" },
// Sort by refs.default descending so "true" values will be first, nulls last
{ $sort: {
"refs.default" : -1
}},
// Group and take the first ref; should either be "default:true" or first element
{ $group: {
_id: "$_id",
name: { $addToSet: "$name" },
refs: { $first: "$refs" }
}},
// (optional) Sort by name to match the example output
{ $sort: {
name: 1,
}},
// (optional) Clean up output
{ $project: {
_id: 0,
name: 1,
refs: 1
}}
)
抽样结果:
{
"result" : [
{
"name" : [
"Book1"
],
"refs" : {
"oid" : "object5",
"default" : true
}
},
{
"name" : [
"Book2"
],
"refs" : {
"oid" : "object5",
"default" : true
}
},
{
"name" : [
"Book3"
],
"refs" : {
"oid" : "object4"
}
},
{
"name" : [
"Book4"
],
"refs" : {
"oid" : "object4",
"default" : true
}
}
],
"ok" : 1
}
备注:
refs
的排序顺序行为进行了假设,其中缺少"default:true“。在简单的测试中,原来的顺序似乎被保留了下来,因此数组的“第一个”元素就像预期的那样。name
是一个单一元素数组,而refs
成为一个嵌入式对象。与其在聚合框架中进一步操作,不如在应用程序代码中引用正确的字段。发布于 2014-02-03 12:14:38
我认为下面的聚合查询可以工作,
db.books.aggregate(
{$unwind:'$refs'},
{$group:{_id:{name:'$name',def:'$refs.default'},refs:{$first:'$refs'}}},
{$sort:{'_id.def':-1}},
{$group:{_id:'$_id.name',refs:{$first:'$refs'}}},
{$project:{name:'$_id',refs:1,_id:0}}
)
结果:
{
"result" : [
{
"refs" : {
"oid" : "object4"
},
"name" : "Book3"
},
{
"refs" : {
"oid" : "object5",
"default" : true
},
"name" : "Book1"
},
{
"refs" : {
"oid" : "object5",
"default" : true
},
"name" : "Book2"
},
{
"refs" : {
"oid" : "object4",
"default" : true
},
"name" : "Book4"
}
],
"ok" : 1
}
https://stackoverflow.com/questions/21525882
复制相似问题