I have documents of the form:
{
_id : ObjectId(.....),
prop1 : "foo",
links : [ 1, 2, 3, 4 ]
}
{
_id : ObjectId(.....),
prop1 : "bar",
links : [ 5, 6, 7, 8 ]
}
I am using the aggregation framework to process these documents, I use $unwind to generate a document for each value in the links array.
But I have three cases where I need to update the documents before calling $unwind, I have been looking at the $project operation, but I can find no information about how to create or update arrays for the following cases.
1) The links property is missing
{
_id : ObjectId(.....),
prop1 : "far"
}
I need to insert the links array
2) The links array property is an empty array
{
_id : ObjectId(.....),
prop1 : "far",
links : []
}
I need to insert a value into the array
3) The links array has too few values
{
_id : ObjectId(.....),
prop1 : "far",
links : [ 9, 10 ]
}
I need to insert additional values into the array
If the value is an array, $push appends the whole array as a single element. To add each element of the value separately, use the $each modifier with $push . For an example, see Append a Value to Arrays in Multiple Documents. For a list of modifiers available for $push , see Modifiers.
The $project takes a document that can specify the inclusion of fields, the suppression of the _id field, the addition of new fields, and the resetting of the values of existing fields. Alternatively, you may specify the exclusion of fields. Specifies the inclusion of a field.
Push and Pull are the two operations used to add and remove elements from arrays in MongoDB documents. Pushing and pulling elements are done using the MongoDB $push and $pull operators, respectively: The $push operator appends a specified value to an array.
The pipeline provides efficient data aggregation using native operations within MongoDB, and is the preferred method for data aggregation in MongoDB. The aggregation pipeline can operate on a sharded collection. The aggregation pipeline can use indexes to improve its performance during some of its stages.
You should be able to use $isNull
(reference):
db.test.aggregate({ $project : { the_links: { $ifNull : ["$links" , [5,6]]}} })
It's simple logic that if the referenced field ($links
) is null, the replacement value (in this case [5, 6]
) is used. I renamed the field to the_links
in the example.
Assuming the links
field is null (and not an empty array). Given data like:
{ "_id" : ObjectId(...), "prop1" : "foo", "links" : [ 1, 2, 3, 4 ] }
{ "_id" : ObjectId(...), "prop1" : "bar" }
The aggregation above produces:
{
"result" : [
{
"_id" : ObjectId("52a869d51d02442354276cff"),
"the_links" : [
1,
2,
3,
4
]
},
{
"_id" : ObjectId("52a869e31d02442354276d00"),
"the_links" : [
5,
6
]
}
],
"ok" : 1
}
If links were an empty array []
rather than null
, you could do something like:
db.test.aggregate({ $project :
{ the_links: { $cond : [ { $eq : ["$links", []]}, '$links', [5,6]]}} })
But, if it's either null or []
, then you'd need to add an additional check for that condition as an $or
within the $cond
operator.
If the list has values, and you want to add more values conditionally, the current (2.4.x) production build of MongoDB does not have an effective solution. The development branch has an operator called $size
which will return the length of an array (jira). You could then conditionally add them using yet another development feature called $setUnion:
$setUnion Takes any number of arrays and returns an array that containing the elements that appear in any input array.
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