有条件地求值数组元素以返回 [英] Conditionally evaluate an array element to return

查看:88
本文介绍了有条件地求值数组元素以返回的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下数据,我想返回默认文档的id结果,以便从MongoDB的Array字段中选择.让我们将集合称为books.样本收集数据如下所示:

Considering the following data, I want to return the results of what id the default document to choose from within an Array field in MongoDB. Let's call the collection books. A sample collection data is shown below:

[
  {
     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 } ]
 }
]

好的.因此,为了简洁起见,其中包含许多关键值,但这并不能改变重点.

Okay. So a lot of the key values are in there for brevity but this doesn't change the point.

此处所需的逻辑如下:

  1. refs数组字段中查找并返回默认值为 true
  2. 的文档
  3. 如果数组中没有匹配的文档,请返回数组中的第一个文档
  1. Find and return the document in the refs Array field that has a default of true
  2. If there is no matching document in the array return the first document in the array

按照这种逻辑,我真的很想看到返回的内容如下:

And following that logic, I would really like to see something returned as follows :

[
  {
    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属性在文档中不存在(可能设置为true但存在就足够了).

Now I know there is the $cond operator in the aggregation pipeline, but part of this condition seems to be bound to getting a $slice on the projection where the default property does not exist on the document ( and is probably set to true but exists should suffice ).

此逻辑模式取决于使用 $ pull 的预期结果a>删除匹配的元素:

This logic pattern rests on the expected results of using $pull to remove the element matching:

oid: "object5"

在每个文档数组中,然后仍然可以后退到查询中数组的第一个元素

Out of each document array and then still be able to fall back to the first element of the array in a query

所以我正在寻找一些 strong fu以便能够返回结果.

So I'm looking for some strong fu to be able to return the results.

解决方案不能在主文档中添加另一个引用数组文档中默认字段值的字段.实际上没有这个要点,因此$pull操作可在 文档更新模式.

And the solution cannot be to add another field in the main document referencing the value of the default field in the array document. Not having this is actually the point so the $pull operation works in a multi document update mode.

编辑

这是一个查询,我的意思是当未设置 default 属性时,我希望列出数组中的第一个元素.每次.

This is intended as a query and I really mean when the default attribute is not set I want the first element in the array as it is listed. Every time.

字符串是样本数据,因此不依赖于词法顺序.在现实世界中,所有object#参考都可能是真实的 $ oid .

The strings are sample data so don't rely on lexical order. All object# references are likely real $oid in the real world.

这可能最终会成为赏金.如上所述,在更新的容忍范围内可以接受模式更改.最糟糕的是,这些发现是JIRA问题的合理依据.

This may end up as a bounty. Schema changes are accepted within the tolerance of the update as mentioned. At worst the findings are a reasonable basis for a JIRA issue.

作为参考,我基于

For reference, I launched this based out of thinking from my answer on this post, which is largely about re-thinking the schema to accommodate the goal.

打猎不错.

PS和 Webscale ,人们.该集合的更新无需迭代就可以进行,因为其中可能确实有很多(哦,webscale!).

P.S And Webscale, people. Updates on the collection need to happen without iteration as there could be a really, really, ( oh webscale! ) big number of them.

推荐答案

下面是一个使用MongoDB 2.4.9中的Aggregation Framework的示例,我认为可以达到您想要的结果:

Here's an example using the Aggregation Framework in MongoDB 2.4.9 that I think achieves the result you are after:

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".在简短测试中,原始顺序似乎已保留,因此数组的第一个"元素符合预期.

  • This makes an assumption on the sort order behaviour for refs where "default:true" is missing. On brief testing the original order appears to be preserved, so the "first" element of the array is as expected.

由于使用了聚合运算符,因此输出name是单个元素数组,而refs成为嵌入式对象.您可以只在应用程序代码中引用正确的字段,而不是在Aggregation Framework中进行进一步的操作.

Due to the aggregation operators used, the output name is a single element array, and refs becomes an embedded object. Rather than manipulating further in the Aggregation Framework, you could just reference the correct fields in your application code.

这篇关于有条件地求值数组元素以返回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆