0

I have a pretty big MongoDB document that holds all kinds of data. I need to identify the fields that are of type array in a collection so I can remove them from the displayed fields in the grid that I will populate.

My method now consists of retrieving all the field names in the collection with

This was taken from the response posted here MongoDB Get names of all keys in collection

mr = db.runCommand({
  "mapreduce" : "Product",
  "map" : function() {
    for (var key in this) { emit(key, null); }
  },
  "reduce" : function(key, stuff) { return null; }, 
  "out": "things" + "_keys"
})

db[mr.result].distinct("_id")

And running for each of the fields a query like this one

db.Product.find( { $where : "Array.isArray(this.Orders)" } ).count()

If there's anything retrieved the field is considered an array.

I don't like that I need to run n+2 queries ( n being the number of different fields in my collection ) and I wouldn't like to hardcode the fields in the model. It would defeat the whole purpose of using MongoDB.

Is there a better method of doing this ?

Community
  • 1
  • 1
Daniel Luca CleanUnicorn
  • 1,087
  • 1
  • 12
  • 30

1 Answers1

0

I made a couple of slight modifications to the code you provided above:

mr = db.runCommand({
  "mapreduce" : "Product",
  "map" : function() {
    for (var key in this) { 
       if (Array.isArray(this[key])) {
          emit(key, 1); 
       } else {
          emit(key, 0);
       }
    }
  },
  "reduce" : function(key, stuff) { return Array.sum(stuff); }, 
  "out": "Product" + "_keys"
})

Now, the mapper will emit a 1 for keys that contain arrays, and a 0 for any that do not. The reducer will sum these up, so that when you check your end result:

db[mr.result].find()

You will see your field names with the number of documents in which they contain Array values (and a 0 for any that are never arrays).

So this should give you which fields contain Array types with just the map-reduce job.

--

Just to see it with some data:

db.Product.insert({"a":[1,2,3], "c":[1,2]})
db.Product.insert({"a":1, "b":2})
db.Product.insert({"a":1, "c":[2,3]})

(now run the "mr =" code above)

db[mr.result].find()
{ "_id" : "_id", "value" : 0 }
{ "_id" : "a", "value" : 1 }
{ "_id" : "b", "value" : 0 }
{ "_id" : "c", "value" : 2 }
bcm360
  • 1,437
  • 2
  • 17
  • 25