profiling - How to search MongoDB-Documents on different nesting levels? -
i'm analyzing system.profile
-collection of mongodb-database. i'd find queries have stage collscan
oder ixscan
. problem is, field stage
can occur on several levels (...
: shortened json):
{ "op" : "query", "ns" : "spt.coll", "query" : { "user" : "userc" }, "ntoreturn" : 1, ... "millis" : 0, "execstats" : { "stage" : "projection", "nreturned" : 1, ... "transformby" : { "settings.arr" : 1 }, "inputstage" : { "stage" : "fetch", "nreturned" : 1, ... "alreadyhasobj" : 0, "inputstage" : { "stage" : "ixscan", "nreturned" : 1, ... "matchtested" : 0 } } }, "ts" : isodate("2015-07-30t09:16:22.551z"), "client" : "127.0.0.1", "allusers" : [ ], "user" : "" }
in above example stage occurs on 3 levels:
"execstats.stage"
"execstats.inputstage.stage"
"execstats.inputstage.inputstage.stage"
there might deeper nested stages. is there way return documents, have stage: "ixscan"
oder stage: "collscan"
on of nesting levels? or have run query each nesting level?
i tried use following function referring how find mongodb field name @ arbitrary depth , unfortunately gives error:
db.system.profile.find( function () { var findkey = "stage", findval = "collscan"; function inspectobj(doc) { return object.keys(doc).some(function(key) { if ( typeof(doc[key]) == "object" ) { return inspectobj(doc[key]); } else { return ( key == findkey && doc[key] == findval ); } }); } return inspectobj(this); } )
error-message:
error: error: { "$err" : "typeerror: object.keys called on non-object\n @ function.keys (native)\n @ inspectobj (_funcs1:6:25)\n @ _funcs1:8:22\n @ array.some (native)\n @ inspectobj (_funcs1:6:35)\n @ _funcs1:8:22\n @ array.some (native)\n @ inspectobj (_funcs1:6:35)\n @ _funcs1 (_funcs1:14:16) near 'rn object.keys(doc).some(function(key) ' (line 6)", "code" : 16722 }
to reproduce above json, use following code:
use spt db.coll.drop() db.coll.insert([ {settings: {arr: ["a", "b"]}, user: "usera"}, {settings: {arr: ["c", "d"]}, user: "userb"}, {settings: {arr: ["e", "f"]}, user: "userc"}, {settings: {arr: ["g", "g"]}, user: "userd"}, ]) db.coll.ensureindex({user: 1}) db.setprofilinglevel(0) db.system.profile.drop() db.setprofilinglevel(2) db.coll.find({user: "userc"}, {"settings.arr": 1}).limit(1).pretty() db.system.profile.find().pretty()
the error mention thrown object.keys
when object not enumerable. easy way catch , ignore error:
db.system.profile.find( // returns documents, function returns true. function () { var findkey = "stage", findval = "collscan"; function inspectobj(doc) { // object.keys(doc) works enumerables (arrays , documents) // https://developer.mozilla.org/en-us/docs/web/javascript/reference/global_objects/object/keys // incoming object might e.g. `isodate("2015-07-29t08:20:42.768z")` // need catch (and ignore) typeerrors thrown object.keys() var contains = false; try { contains = object.keys(doc).some(function(key) { cval = doc[key]; if ( typeof(cval) == "object" ) { // recursive call if value object. return inspectobj(doc[key]); } else { return ( key == findkey && doc[key] == findval ); } }); } catch(typeerror) { // ignore typeerror } return contains; } return inspectobj(this); }, {op: 1, ns:1, query: 1} )
Comments
Post a Comment