$unwind 聚合框架中的对象 [英] $unwind an object in aggregation framework

查看:9
本文介绍了$unwind 聚合框架中的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 MongoDB 聚合框架中,我希望在对象(即 JSON 集合)上使用 $unwind 运算符.看起来这不是可能,有解决方法吗?有计划实施吗?

In the MongoDB aggregation framework, I was hoping to use the $unwind operator on an object (ie. a JSON collection). Doesn't look like this is possible, is there a workaround? Are there plans to implement this?

例如,从聚合 documentation 中获取文章集合.假设有一个附加字段ratings",它是来自 user -> rating 的映射.你能计算出每个用户的平均评分吗?

For example, take the article collection from the aggregation documentation . Suppose there is an additional field "ratings" that is a map from user -> rating. Could you calculate the average rating for each user?

除此之外,我对聚合框架非常满意.

Other than this, I'm quite pleased with the aggregation framework.

更新:这是我每个请求的 JSON 集合的简化版本.我正在存储基因组数据.我不能真正使基因型成为一个数组,因为最常见的查找是获取随机人的基因型.

Update: here's a simplified version of my JSON collection per request. I'm storing genomic data. I can't really make genotypes an array, because the most common lookup is to get the genotype for a random person.

variants: [

    {
        name: 'variant1', 
        genotypes: {

            person1: 2,
            person2: 5,
            person3: 7,

        }
    }, 

    {
        name: 'variant2', 
        genotypes: {

            person1: 3,
            person2: 3,
            person3: 2,

        }
    }

]

推荐答案

不可能使用聚合框架进行您所描述的计算类型 - 而且它 不是 因为没有 $unwind 方法用于非数组.即使 person:value 对象是数组中的文档,$unwind 也无济于事.

It is not possible to do the type of computation you are describing with the aggregation framework - and it's not because there is no $unwind method for non-arrays. Even if the person:value objects were documents in an array, $unwind would not help.

分组依据"功能(无论是在 MongoDB 中还是在任何关系数据库中)都是根据字段或列的值完成的.我们按字段值分组,并根据另一个字段的值求和/平均/等.

The "group by" functionality (whether in MongoDB or in any relational database) is done on the value of a field or column. We group by value of field and sum/average/etc based on the value of another field.

简单示例是您建议的变体,评分字段添加到示例文章集合中,但不是从用户到评分的映射,而是像这样的数组:

Simple example is a variant of what you suggest, ratings field added to the example article collection, but not as a map from user to rating but as an array like this:

{ title : title of article", ...
  ratings: [
         { voter: "user1", score: 5 },
         { voter: "user2", score: 8 },
         { voter: "user3", score: 7 }
  ]
}

现在您可以将其汇总为:

Now you can aggregate this with:

[ {$unwind: "$ratings"},
  {$group : {_id : "$ratings.voter", averageScore: {$avg:"$ratings.score"} } } 
]

但这个示例的结构如您所描述的那样:

But this example structured as you describe it would look like this:

{ title : title of article", ...
  ratings: {
         user1: 5,
         user2: 8,
         user3: 7
  }
}

甚至这个:

{ title : title of article", ...
  ratings: [
         { user1: 5 },
         { user2: 8 },
         { user3: 7 }
  ]
}

即使你可以 $unwind 这个,这里也没有什么可以聚合的.除非您知道所有可能的密钥(用户)的完整列表,否则您无法对此做太多事情.[*]

Even if you could $unwind this, there is nothing to aggregate on here. Unless you know the complete list of all possible keys (users) you cannot do much with this. [*]

与您所拥有的类似的关系数据库架构:

An analogous relational DB schema to what you have would be:

CREATE TABLE T (
   user1: integer,
   user2: integer,
   user3: integer
   ...
);

我们不会这样做,而是这样做:

That's not what would be done, instead we would do this:

CREATE TABLE T (
   username: varchar(32),
   score: integer
);

现在我们使用 SQL 进行聚合:

and now we aggregate using SQL:

select username, avg(score) from T group by username;

有一个对 MongoDB 的增强请求,可能允许您将来在聚合框架中执行此操作 - 将值投影到键的能力,反之亦然.同时,总是有 map/reduce.

There is an enhancement request for MongoDB that may allow you to do this in the aggregation framework in the future - the ability to project values to keys to vice versa. Meanwhile, there is always map/reduce.

[*] 如果您知道所有唯一键,则有一种复杂的方法可以做到这一点(您可以使用类似于 this) 但如果你知道所有的键,你也可以只运行 db.articles.find 形式的一系列查询({"ratings.user1":{$exists:true}},{_id:0,"ratings.user1":1}) 对于每个 userX,这将返回他们的所有评分,您可以对它们进行求和和平均足够简单,而不是进行聚合框架所需的非常复杂的投影.

[*] There is a complicated way to do this if you know all unique keys (you can find all unique keys with a method similar to this) but if you know all the keys you may as well just run a sequence of queries of the form db.articles.find({"ratings.user1":{$exists:true}},{_id:0,"ratings.user1":1}) for each userX which will return all their ratings and you can sum and average them simply enough rather than do a very complex projection the aggregation framework would require.

这篇关于$unwind 聚合框架中的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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