How can I find all documents in a MongoDb collection where a property of the document or its sub-documents contains an empty object value {}
?
The name of the property is not known.
Example of which documents should be returned:
{
data: {
comment: {}
}
}
As said data
and comment
as property names are unknown.
In MongoDB, we can check the existence of the field in the specified collection using the $exists operator. When the value of $exists operator is set to true, then this operator matches the document that contains the specified field(including the documents where the value of that field is null).
MongoDB fetch documents containing 'null' If we want to fetch documents from the collection "testtable" which contains the value of "interest" is null, the following mongodb command can be used : >db. testtable. find( { "interest" : null } ).
Find() Method. In MongoDB, find() method is used to select documents in a collection and return a cursor to the selected documents.
To get stats about MongoDB server, type the command db. stats() in MongoDB client. This will show the database name, number of collection and documents in the database.
The way to iterate object properties within aggregation pipeline is $objectToArray operator, which converts a document to the array of key-value pairs. Unfortunately, it does not flatten embedded documents. Until such support is implemented, I don't see a way to accomplish your task with the pure aggregation pipeline.
However you could always use $where operator and put the logic into JavaScript code. It should recursively iterate over all document properties and check whether the value is an empty document. Here is a working sample:
db.collection.find({"$where" : function () {
function hasEmptyProperties(doc) {
for (var property in doc) {
var value = doc[property];
if (value !== null && value.constructor === Object &&
(Object.keys(value).length === 0 || hasEmptyProperties(value))) {
return true;
}
}
return false;
}
return hasEmptyProperties(this);
}});
If you fill the collection with the following data:
db.collection.insert({ _id: 1, p: false });
db.collection.insert({ _id: 2, p: [] });
db.collection.insert({ _id: 3, p: null });
db.collection.insert({ _id: 4, p: new Date() });
db.collection.insert({ _id: 5, p: {} });
db.collection.insert({ _id: 6, nestedDocument: { p: "Some Value" } });
db.collection.insert({ _id: 7, nestedDocument: { p1: 1, p2: {} } });
db.collection.insert({ _id: 8, nestedDocument: { deepDocument: { p: 1 } } });
db.collection.insert({ _id: 9, nestedDocument: { deepDocument: { p: {} } } });
the query will correctly detect all documents with empty properties:
{ "_id" : 5, "p" : { } }
{ "_id" : 7, "nestedDocument" : { "p1" : 1, "p2" : { } } }
{ "_id" : 9, "nestedDocument" : { "deepDocument" : { "p" : { } } } }
Just for reference, here is an aggregation pipeline based on $objectToArray
which detects empty properties, however not within nested documents:
db.collection.aggregate(
[
{ "$project": {
_id: 1,
"properties": { "$objectToArray": "$$ROOT" }
}},
{ "$project": {
_id: 1,
propertyIsEmpty: {
$map: {
input: "$properties.v",
as: "value",
in: { $eq: ["$$value", {} ] }
}
}
}},
{ "$project": {
_id: 1,
anyPropertyIsEmpty: { $anyElementTrue: [ "$propertyIsEmpty" ] }
}},
{$match : {"anyPropertyIsEmpty" : true}},
{ "$project": {
_id: 1,
}},
]);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With