mongodb - Aggregation framework flatten subdocument data with parent document -
i building dashboard rotates between different webpages. wanting pull slides part of "test" deck , order them appropriately. after query result ideally like.
class="lang-js prettyprint-override">[ { "url" : "http://10.0.1.187", "position": 1, "duartion": 10 }, { "url" : "http://10.0.1.189", "position": 2, "duartion": 3 } ] i have dataset looks following
class="lang-js prettyprint-override">{ "_id" : objectid("53a612043c24d08167b26f82"), "url" : "http://10.0.1.189", "decks" : [ { "title" : "test", "position" : 2, "duration" : 3 } ] } { "_id" : objectid("53a6103e3c24d08167b26f81"), "decks" : [ { "title" : "test", "position" : 1, "duration" : 2 }, { "title" : "other deck", "position" : 1, "duration" : 10 } ], "url" : "http://10.0.1.187" } my attempted query looks like:
class="lang-js prettyprint-override">db.slides.aggregate([ { "$match": { "decks.title": "test" } }, { "$sort": { "decks.position": 1 } }, { "$project": { "_id": 0, "position": "$decks.position", "duration": "$decks.duration", "url": 1 } } ]); but not yield desired results. how can query dataset , expected results in optimal way?
well "flatten" document title suggests $unwind going employed there not other way that. there different approaches if can live array beingness filtered downwards matching element.
basically speaking, if have 1 thing match in array fastest approach utilize .find() matching required element , projecting:
db.slides.find( { "decks.title": "test" }, { "decks.$": 1 } ).sort({ "decks.position": 1 }).pretty() that still array long have 1 element matches work. items sorted expected, though of course of study "title" field not dropped matched documents, beyond possibilities simple projection.
class="lang-js prettyprint-override">{ "_id" : objectid("53a6103e3c24d08167b26f81"), "decks" : [ { "title" : "test", "position" : 1, "duration" : 2 } ] } { "_id" : objectid("53a612043c24d08167b26f82"), "decks" : [ { "title" : "test", "position" : 2, "duration" : 3 } ] } another approach, long have mongodb 2.6 or greater available, using $map operator , others in order both "filter" , re-shape array "in-place" without applying $unwind:
db.slides.aggregate([ { "$project": { "url": 1, "decks": { "$setdifference": [ { "$map": { "input": "$decks", "as": "el", "in": { "$cond": [ { "$eq": [ "$$el.title", "test" ] }, { "position": "$$el.position", "duration": "$$el.duration" }, false ] } } }, [false] ] } }}, { "$sort": { "decks.position": 1 }} ]) the advantage there can create changes without "unwinding", can cut down processing time big arrays not creating new documents every array fellow member , running separate $match stage "filter" or $project reshape.
{ "_id" : objectid("53a6103e3c24d08167b26f81"), "decks" : [ { "position" : 1, "duration" : 2 } ], "url" : "http://10.0.1.187" } { "_id" : objectid("53a612043c24d08167b26f82"), "url" : "http://10.0.1.189", "decks" : [ { "position" : 2, "duration" : 3 } ] } you can 1 time again either live "filtered" array or if want can 1 time again "flatten" adding in additional $unwind not need filter $match result contains matched items.
but speaking if can live utilize .find() fastest way. otherwise doing fine little data, or there other alternative consideration.
mongodb aggregation-framework
No comments:
Post a Comment