考虑到以下数据,我想在MongoDB的Array字段中返回默认文档ID的结果。让我们调用集合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运算符,但是这个条件的一部分似乎必然会在default
属性没有的投影上获得$slice存在于文档上(可能设置为true但存在应该足够)。
此逻辑模式依赖于使用$pull删除元素匹配的预期结果:
oid: "object5"
在每个文档数组中,然后仍然能够回退到查询中数组的第一个元素
所以我正在寻找一些强大 fu
才能返回结果。
解决方案不能在主文档中添加另一个字段,引用数组文档中默认字段的值。没有这个实际上就是重点,因此$pull
操作在multi文档更新模式下有效。
修改
这是一个查询,我的意思是当未设置默认属性时,我想要列出数组中的第一个元素。每一次。
字符串是样本数据,所以不要依赖词汇顺序。在现实世界中,所有object#
引用都可能是真正的 $ oid 。
这可能最终成为赏金。如上所述,在更新的容差范围内接受模式更改。在最坏的情况下,这些发现是JIRA问题的合理依据。
作为参考,我基于this post的答案开始思考,这主要是为了重新思考架构以适应目标。
好狩猎。
P.S和Webscale,人们。集合的更新需要在没有迭代的情况下进行,因为可能存在真正的(哦网络规模!)大量数据。
答案 0 :(得分:2)
以下是使用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
成为嵌入对象。您可以在应用程序代码中引用正确的字段,而不是在聚合框架中进一步操作。
答案 1 :(得分:1)
我认为以下聚合查询将起作用,
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
}