Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get names of all keys in the collection and subdocuments

I need to get all the field names from my collection, including fields in subdocuments. I am currently running this command and getting only the names of the root fields. How can I get all field names?

My collection looks like this:

"UserId" : 11111,
"Personal" : {
    "Email" : "[email protected]",
    "FirstName" : "Name",
    "LastName" : "Last"
},
"Car" : {
    "CarType" : "NULL"
}

This is the command

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

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

I want this result:

UserId, Personal.Email, Personal.FirstName, Personal.LastName, Car.CarType

like image 585
Guilherme Ferreira Avatar asked Feb 12 '19 14:02

Guilherme Ferreira


2 Answers

In plain Javascript, you could take an iterative and recursive approach by looking at the object, their keys and their nested objects.

function getKeys(object) {
    if (!object || typeof object !== 'object') {
        return [];
    }
    if (Array.isArray(object)) {
        return object.reduce((r, o) => [...r, ...getKeys(o)], []);
    }
    return Object.keys(object).reduce((r, k) => [...r, k, ...getKeys(object[k])], []);
}

var object = { UserId: 11111, Personal: { Email: "[email protected]",  FirstName: "Name", LastName: "Last" }, Car: { CarType: "NULL" }, array: [{ foo: '', bar: '' }, { foo: '', bar: '' }] };

console.log(getKeys(object));
like image 158
Nina Scholz Avatar answered Nov 14 '22 23:11

Nina Scholz


You can use below aggregation

db.collection.aggregate([
  { "$project": { "data": { "$objectToArray": "$$ROOT" }}},
  { "$project": {
    "data": {
      "$map": {
        "input": "$data",
        "in": {
          "$cond": [
            { "$eq": [{ "$type": "$$this.v" }, "object"] },
            { "k": "$$this.k", "v": { "$objectToArray": "$$this.v" }},
            "$$this"
          ]
        }
      }
    }
  }},
  { "$project": {
    "data": {
      "$map": {
        "input": "$data",
        "as": "d",
        "in": {
          "k": "$$d.k",
          "v": {
            "$map": {
              "input": { "$cond": [{ "$eq": [{ "$type": "$$d.v" }, "array"] }, "$$d.v", []] },
              "as": "v",
              "in": { "v": { "$concat": ["$$d.k", ".", "$$v.k"] }}
            }
          }
        }
      }
    }
  }},
  { "$project": {
    "finalKeys": {
      "$concatArrays": [
        { "$reduce": {
          "input": "$data.v",
          "initialValue": [],
          "in": { "$concatArrays": ["$$value", "$$this.v"] }
        }},
        "$data.k"
      ]
    }
  }}
])

Output

[
  {
    "finalKeys": [
      "Personal.Email",
      "Personal.FirstName",
      "Personal.LastName",
      "Car.CarType",
      "_id",
      "UserId",
      "Personal",
      "Car"
    ]
  }
]
like image 40
Ashh Avatar answered Nov 15 '22 00:11

Ashh