aggregation framework nested array return project value

1,838 views
Skip to first unread message

Jack Xu

unread,
Aug 14, 2012, 4:17:51 PM8/14/12
to mongod...@googlegroups.com
I would like to use aggregation framework on documents like in http://www.mongodb.org/display/DOCS/Using+Multikeys+to+Simulate+a+Large+Number+of+Indexes, which looks like below:

x = {
 _id : "abc",
 cost : 33,
 attribs : [
          { color : 'red' },
          { shape : 'rect' },
          { avail : true } ]
 };
db.foo.insert(x);

I would like to get all the colors, but when I ran the following, I got an array instead. 

db.foo.aggregate(
  { $project : {
     a : "$attribs.color"
  } }
);

{
"result" : [
{
"_id" : "abc",
"a" : [
"red",
null,
null
]
}
],
"ok" : 1
}

any way I can get a single value instead of an array with nulls?

Stephen Steneker

unread,
Aug 15, 2012, 7:59:59 AM8/15/12
to mongod...@googlegroups.com
any way I can get a single value instead of an array with nulls?

Hi Jack,

You can use the $group operator with $addToSet to combine results into a set of unique names without nulls.

Commented example based on your schema sample:

db.foo.aggregate(

 // Find values of 'color' for each document
 { $project : { a : "$attribs.color" }},
 // Unwind 'color' matches per document into single array
 { $unwind : "$a" },
 // Group unique names into a set (removing nulls) .. must specify _id
 { $group : {
_id: "colors",
colors: { $addToSet: "$a" }
 }},
 // Final output, with unwanted _id field removed
 { $project : {
'_id' : 0,
'colors' : 1,
 }}
)

The last step in the pipeline ($project to remove _id) isn't strictly needed if you just want the colors[] array created in the $group step.

A helpful way to understand how the operators manipulate the results is to add one pipeline step at a time (eg. just $project, then $project + $unwind, ..).

My sample output:

{
"result" : [
{
"colors" : [
"green",
"red"
]
}
],
"ok" : 1
}

Cheers,
Stephen

Jack Xu

unread,
Aug 15, 2012, 8:54:30 AM8/15/12
to mongod...@googlegroups.com
Thanks, Stephen! Much appreciated.

my challenge is to find the right operator... 

in my case, assuming the keys are unique, in other words, there is only one color, one shape etc and I would like to do a $group to get summary of the data... for instance, there is a pair called price, I would like to get the average price for all the documents. With the current return value being an array, I can't do so. 

any suggestions?

for 

Stephen Steneker

unread,
Aug 15, 2012, 9:44:51 AM8/15/12
to mongod...@googlegroups.com
Thanks, Stephen! Much appreciated.

my challenge is to find the right operator... 

in my case, assuming the keys are unique, in other words, there is only one color, one shape etc and I would like to do a $group to get summary of the data... for instance, there is a pair called price, I would like to get the average price for all the documents. With the current return value being an array, I can't do so. 

Hi Jack,

You should be able to transform the aggregate results as needed including calculating the average (using $avg function within a $group): http://docs.mongodb.org/manual/reference/aggregation/#_S_group

What would you be grouping by .. average price for all documents regardless of colours?  Can you provide an example of the JSON output results you are trying to get?

You might also find the aggregation examples helpful:

Cheers,
Stephen
Reply all
Reply to author
Forward
0 new messages