If you are working with the latest version of MongoDB 3.4.4, then utilizing $objectToArray
in an aggregate statement alongside $redact
is incredibly efficient. This method allows for native operators to be used which results in a very fast processing speed compared to other methods available.
db[collname].aggregate([
{ "$redact": {
"$cond": {
"if": {
"$gt": [
{ "$size": { "$filter": {
"input": { "$objectToArray": "$$ROOT" },
"as": "doc",
"cond": {
"$eq": [ { "$substr": [ "$$doc.k", 0, 2 ] }, "fk" ]
}
}}},
0
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
The functionality of $objectToArray
which transforms an "object" into key-value pairs in an array format provides great insight into document structure. With the use of $$ROOT
, representing the current document object, we can easily extract and examine these key-value pairs.
For obtaining a unique list of matching keys, the optimized approach in MongoDB 3.4.4 would involve:
db[collname].aggregate([
{ "$redact": {
"$cond": {
"if": {
"$gt": [
{ "$size": { "$filter": {
"input": { "$objectToArray": "$$ROOT" },
"as": "doc",
"cond": {
"$eq": [ { "$substr": [ "$$doc.k", 0, 2 ] }, "fk" ]
}
}}},
0
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}},
{ "$project": {
"j": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"as": "doc",
"cond": {
"$eq": [ { "$substr": [ "$$doc.k", 0, 2 ] }, "fk" ]
}
}
}
}},
{ "$unwind": "$j" },
{ "$group": { "_id": "$j.k" }}
])
Alternatively, if certain conditions are met where the key is always present and there is only one occurrence, the aggregation process can be simplified by using $group
:
db[colname].aggregate([
{ "$group": {
"_id": {
"$arrayElemAt": [
{ "$map": {
"input": { "$filter": {
"input": { "$objectToArray": "$$ROOT" },
"as": "doc",
"cond": {
"$eq": [ { "$substr": [ "$$doc.k", 0, 2 ] }, "fk" ]
}
}},
"as": "el",
"in": "$$el.k"
}},
0
]
}
}}
])
In earlier versions of MongoDB, utilizing the $where
syntax was prevalent for evaluating JavaScript expressions. While not the most efficient method due to JavaScript evaluation overhead, it allowed for dynamic analysis of keys within documents:
db[collname].find(function() { return Object.keys(this).some( k => /^fk/.test(k) ) })
This expression can also be structured using standard query syntax as demonstrated below:
db[collname].find({ "$where": "return Object.keys(this).some( k => /^fk/.test(k) )" })
Ultimately, the choice between different approaches depends on the specific requirements of your data model and processing needs.