Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-6768

MongoDB Profiler creates illegal documents

    • Type: Icon: Improvement Improvement
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: 2.0.4, 2.6.4, 2.7.6
    • Component/s: Diagnostics
    • Environment:
      Linux (Debian). N/A, really.
    • Query

      The DB profiler creates illegal documents. These documents contain:
      1) keys with $ in the name
      2) keys with . in the name

      This problem makes working with these documents incredibly difficult.

      Here's an example:

      PRIMARY> test.record = db.system.profile.findOne({"ts" : ISODate("2012-08-12T14:26:18.806Z")})
      {
      	"ts" : ISODate("2012-08-12T14:26:18.806Z"),
      	"op" : "query",
      	"ns" : "gimmebar.collectionassets",
      	"query" : {
      		"$query" : {
      			"collection_id" : "redacted"
      		},
      		"$orderby" : {
      			"date" : -1
      		}
      	},
      	"ntoreturn" : 5,
      	"nscanned" : 169,
      	"scanAndOrder" : true,
      	"nreturned" : 5,
      	"responseLength" : 325,
      	"millis" : 227,
      	"client" : "redacted",
      	"user" : ""
      }
      
      PRIMARY> db.tmp_profiler_test.insert(testrecord)
      Tue Aug 14 18:39:40 uncaught exception: field names cannot start with $ [$query]
      

      The same thing happens for $orderby, $or, $set, etc., as well as for keys with "." in the name.

      I think the profiler should not create documents that can't be inserted. (I had to insert them into another collection because I wanted to filter the profiler data set, but I can't delete from a capped collection, which db.system.profile is.)

      I realize this changes the data format of the profiler, but it seems like the right move to me.

      As a workaround, for those developers who might stumble upon this, I managed to get the following transposition to work, but it's far from ideal:

      // recursion is fun
      function rename$(r) {
          for (k in r) {
              var changed = false;
              var newk = k;
              if (newk.indexOf(".") != -1) {
                  changed = true;
                  newk = newk.replace(".", "_DOT_", "g");
              }
              if (newk.indexOf("$") != -1) {
                  changed = true;
                  newk = newk.replace("$", "_DOLLAR_", "g");
              }
              if (changed) {
                  r[newk] = r[k];
                  delete r[k];
              }
              if (typeof r[newk] == "object") {
                  r[newk] = rename$(r[newk]);
              }
          }
          return r;
      }
      
      db.tmp_profiler_test.drop();
      db.system.profile.find(query_parameters).forEach(function(r) { r = rename$(r); db.tmp_profiler_test.insert(r);})
      

      (I also couldn't get this box to respect wiki markup, so editor: feel free to fix.) [Done.]

            Assignee:
            backlog-server-query Backlog - Query Team (Inactive)
            Reporter:
            scoates Sean Coates
            Votes:
            1 Vote for this issue
            Watchers:
            13 Start watching this issue

              Created:
              Updated:
              Resolved: