paging subdocument in mongodb subdocument -
i want paging data in mongodb. use slice operator can not paging data. wish bring row can not paging in row.
i want return 2 rows of data source.
how can resolve
my query :
db.getcollection('forms').find({ "_id": objectid("557e8c93a6df1a22041e0879"), "questions._id": objectid("557e8c9fa6df1a22041e087b") }, { "questions.$.datasource": { "$slice": [0, 2] }, "_id": 0, "questions.datasourceitemcount": 1 }) my collection data :
/* 1 */ { "_id" : objectid("557e8c93a6df1a22041e0879"), "questioncount" : 2.0000000000000000, "questions" : [ { "_id" : objectid("557e8c9ba6df1a22041e087a"), "datasource" : [], "datasourceitemcount" : numberlong(0) }, { "_id" : objectid("557e8c9fa6df1a22041e087b"), "datasource" : [ { "_id" : objectid("557e9428a6df1a198011fa55"), "creationdate" : isodate("2015-06-15t09:00:24.485z"), "isactive" : true, "text" : "sdf", "value" : "sdf" }, { "_id" : objectid("557e98e9a6df1a1a88da8b1d"), "creationdate" : isodate("2015-06-15t09:20:41.027z"), "isactive" : true, "text" : "das", "value" : "asdf" }, { "_id" : objectid("557e98eea6df1a1a88da8b1e"), "creationdate" : isodate("2015-06-15t09:20:46.889z"), "isactive" : true, "text" : "asdf", "value" : "asdf" }, { "_id" : objectid("557e98f2a6df1a1a88da8b1f"), "creationdate" : isodate("2015-06-15t09:20:50.401z"), "isactive" : true, "text" : "asd", "value" : "asd" }, { "_id" : objectid("557e98f5a6df1a1a88da8b20"), "creationdate" : isodate("2015-06-15t09:20:53.639z"), "isactive" : true, "text" : "asd", "value" : "asd" } ], "datasourceitemcount" : numberlong(5) } ], "name" : "er" }
though possible real wrangling best off changing document structure "flatten" array entries single array. main reason "updates" not atomically supported mongodb respect updating "inner" array due current limitations of positional $ operator.
at rate, it's not easy deal reasons become apparent.
for present structure approach this:
db.collection.aggregate([ // match required document , `_id` unique { "$match": { "_id": objectid("557e8c93a6df1a22041e0879") }}, // unwind outer array { "$unwind": "$questions" }, // match inner entry { "$match": { "questions._id": objectid("557e8c9fa6df1a22041e087b"), }}, // unwind inner array { "$unwind": "$questions.datasource" } // find first element { "$group": { "_id": { "_id": "$_id", "questionid": "$questions._id" }, "firstsource": { "$first": "$questions.datasource" }, "sources": { "$push": "$questions.datasource" } }}, // unwind sources again { "$unwind": "$sources" }, // compare elements keep { "$project": { "firstsource": 1, "sources": 1, "seen": { "$eq": [ "$firstsource._id", "$sources._id" ] } }}, // filter out "seen" { "$match": { "seen": true } }, // group elements want { "$group": { "_id": "$_id", "firstsource": "$firstsource", "secondsource": { "$first": "$sources" } }} ]) so going give "first 2 elements" of inner array. it's basic process implementing $slice in aggregation framework, is required since cannot use standard projection "nested array" in way trying.
since $slice not supported otherwise aggregation framework, can see doing "paging" pretty horrible , "iterative" operation in order "pluck" array elements.
i @ point suggest "flattening" single array, same "slicing" problem applies because if made "questionid" property of "inner" data, has same projection selection problems need same aggregation approach.
then there "seemingly" not great structure data ( query operations ) depends on usage patterns. structure suits type of operation:
{ "_id" : objectid("557e8c93a6df1a22041e0879"), "questioncount" : 2.0000000000000000, "questions" : { "557e8c9ba6df1a22041e087a": { "datasource" : [], "datasourceitemcount" : numberlong(0) }, "557e8c9fa6df1a22041e087b": { "datasource" : [ { "_id" : objectid("557e9428a6df1a198011fa55"), "creationdate" : isodate("2015-06-15t09:00:24.485z"), "isactive" : true, "text" : "sdf", "value" : "sdf" }, { "_id" : objectid("557e98e9a6df1a1a88da8b1d"), "creationdate" : isodate("2015-06-15t09:20:41.027z"), "isactive" : true, "text" : "das", "value" : "asdf" } ], "datasourceitemcount" : numberlong(5) } } } where works:
db.collection.find( { "_id": objectid("557e8c93a6df1a22041e0879"), "questions.557e8c9fa6df1a22041e087b": { "$exists": true } }, { "_id": 0, "questions.557e8c9fa6df1a22041e087b.datasource": { "$slice": [0, 2] }, "questions.557e8c9fa6df1a22041e087b.datasourceitemcount": 1 } ) nested arrays not great many operations, particularly update operations since not possible "inner" array index update operations. positional $ operator "first" or "outer" array index , cannot "also" match inner array index.
updates structure have involve "reading" document whole , manipulating in code , writing back. there no "guarantee" document has not changed in collection between operations , can lead inconsistencies unless handled properly.
on other hand, revised structure shown, works type of query given, may "bad" if need dynamically search or "aggregate" across have represented "outer" "questions".
data structure mongodb subjective "how use it". best consider of usage patterns before "nailing down" final data structure design application.
so can either take note of problems , solutions noted, or live retrieving "outer" element via standard "positional" match , "slice" in client code.
it's matter of "what suits application best".
Comments
Post a Comment