首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >有条件地计算要返回的数组元素

有条件地计算要返回的数组元素
EN

Stack Overflow用户
提问于 2014-02-03 11:14:31
回答 2查看 1.4K关注 0票数 2

考虑到以下数据,我希望返回默认文档在MongoDB的数组字段中选择的结果。让我们调用集合books。样本收集数据如下所示:

代码语言:javascript
运行
复制
[
  {
     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 } ]
 }
]

好吧。因此,为了简洁起见,很多关键值都在其中,但这并没有改变重点。

这里所需的逻辑如下:

  1. refs数组字段中查找并返回文档,该字段的默认值为true
  2. 如果数组中没有匹配的文档,则返回数组中的第一个文档。

按照这一逻辑,我非常希望看到一些东西返回如下:

代码语言:javascript
运行
复制
[
  {
    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删除元素匹配的预期结果:

代码语言:javascript
运行
复制
oid: "object5"

从每个文档数组中退出,然后仍然能够将返回到查询中数组的第一个元素。

因此,我正在寻找一些强 fu,以便能够返回结果。

解决方案不能在主文档中添加另一个字段,引用数组文档中默认字段的值。实际上,没有这一点,所以$pull操作在多点文档更新模式下工作。

编辑

这是作为一个查询,我的意思是当默认的属性没有设置时,我需要数组中的第一个元素,因为它是列出的。每次都是这样。

字符串是示例数据,因此不依赖词法顺序。在现实世界中,所有object#引用都可能是真实的$oid。

这可能最终会成为赏金。如上所述,在允许更新的范围内接受架构更改。最糟糕的是,这些调查结果是JIRA问题的合理依据。

作为参考,我从我对这个职位的回答中提出了这一观点,这主要是关于重新思考模式以适应目标。

狩猎不错。

P.S和网秤,各位。对集合的更新需要在没有迭代的情况下进行,因为可能会有一个真的,真的,(哦,webscale!)很多人。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-02-03 12:11:45

下面是一个使用MongoDB 2.4.9中的聚合框架的示例,我认为它达到了您所追求的结果:

代码语言:javascript
运行
复制
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
    }}
)

抽样结果:

代码语言:javascript
运行
复制
{
    "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成为一个嵌入式对象。与其在聚合框架中进一步操作,不如在应用程序代码中引用正确的字段。
票数 2
EN

Stack Overflow用户

发布于 2014-02-03 12:14:38

我认为下面的聚合查询可以工作,

代码语言:javascript
运行
复制
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}}
)

结果:

代码语言:javascript
运行
复制
{
    "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

}

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21525882

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档