Docs:
{
_id: 1,
items: [{thing: 5}, {thing: 7}]
}
{
_id: 2,
items: [{thing: 5}, {thing: 11}]
}
I would like to remove all docs from the collection above if all elements in array have "thing" < 10. IE for that case doc 1 should be removed, doc 2 should remain.
Is it possible with a query to find only docs where all elements in the array match with a $lt query?
I tried this:
db.mycollection.remove({items: {$all: [{$elemMatch: {thing: {$lt: 11}}}]}})
However that will remove all docs if any of the elements in the array match the condition.
Use double negative (De-Morgan law):
{items: {$not: {$elemMatch: {thing: {$gte: 11}}}}}
Related
I have a collection people. It has an array field numbers, where each document has a varying number of elements in said array.
My goal is to keep the elements in the 0th index and recursively remove the rest. How could I go about doing this?
For example:
{_id: 1, numbers: [100, 200, 300]}, -> {_id: 1, numbers: [100]},
{_id: 2, numbers: [101, 201]}, -> {_id: 2, numbers: [101]}
{_id: 3, numbers: [102, 202, 400, 500]}, -> {_id: 3, numbers: [102]},
An alternative solution to #R2D2 is to use $slice. Unlike $first, $slice works for more than one element.
collection.updateMany(
{},
{ $push: { numbers: { $each: [], $slice: 1 } } }
);
You could also use $slice: -1 to start from the last element.
See this on Mongo Playground.
You can use the operator $first in update pipeline as follow:
db.collection.update({},
[
{
$addFields: {
numbers: {
$first: "$numbers"
}
}
}
],
{
multi: true
})
Explained:
Replace the "numbers" array in all documents with array with only the first element taken from "numbers"
Playground
If you want the "numbers" to be still of type array you can enclose the output from $first in square brackets [] as follow:
numbers: [{
$first: "$numbers"
}]
Playground 2
Btw , $first is alias of $arrayElemAt that you can use to extract other elements from the array ...
But afcourse the operation can be done via $slice as mentioned earlier by #Clashsoft
I have a mongodb collection.
{ user_id: 1,
items : [ { _id: 1 }, { _id: 2}, {_id:3} ] }
I want to remove the items of the array having specific id. Can anybody explain what is wrong with the above query.
db.col.findOneAndUpdate({user_id:1},{$pull:{items:{$elemMatch:{_id:2}}}})
$pull takes an expression as a parameter so you don't have to use $elemMatch (doesn't work in this case). Try:
db.col.update({user_id:1},{$pull:{items:{_id:2}}})
So expression in this case means that MongoDB will remove the document having _id set to 2 but that document can have other properties as well.
Suppose I have the following item structure:
"_id": "12325523623453254",
"blas": {
"blaA": 0,
"blaB": 0,
"blaC": 0,
"blaD": 1,
}
}
I like to find the items with "blas" including at least one non zero value.
You can do this with an $or query that uses dot notation in the keys to access the fields within blas:
db.test.find({$or: [
{'blas.blaA': {$ne: 0}},
{'blas.blaB': {$ne: 0}},
{'blas.blaC': {$ne: 0}},
{'blas.blaD': {$ne: 0}}
]})
I have a document with the following structure:
[{
"items": [
{
"sent_to_lab": 123,
"received_from_lab": 456,
},
{
"sent_to_lab": 123,
},
]
}
... more orders ...
]
I want to fetch all orders where at least one item matches the following criteria:
'$and': [
{'items.sent_to_lab': {'$exists': True}},
{'items.received_from_lab': {'$exists': False}},
]
So in this case, I would like to return the aforementioned item, because at least one element of the items array matches my criteria.
How can I do this in mongo?
You need to use the $elemMatch operator:
db.collection.find({items:
{$elemMatch:{
sent_to_lab:{$exists:true},
received_from_lab:{$exists:false}}
})
This is query $elemMatch - if you only want to get back the item that matched the condition (and not the entire document with the whole array) then you can use the projection $elemMatch operator similarly.
I tangle a bit in jungles of query and update selectors of MongoDb.
Situation: We have Companies collection. smth like this
Companies.find({}) =>
{_id: 1, item_amount: 5},
{_id: 2, item_amount: 7},
{_id: 3, item_amount: 10}
And we have Users collection with some structure. User want to buy any item and it may decrement value in Companies and increment in Users, with one condition - user may know where he buy the item.
{userId: _id,
ownedItems:
[{company_id: 2, item_amount: 3},
{company_id: 1, item_amount: 5}]
}
Ok. How i may Users.update(), if user want to buy, for example, 5 items from {_id: 3} (we don't know if user has field for company_id: 3)
I thought it may be smth like this:
Companies.update({_id: 3}, {$inc: {item_amount: - 5}})
&&
Users.update({userId: _id}, {$set: {'ownedItems[x].company_id': 3}, $inc{'ownedItems[x].item_amount': 5})
But of cause there are some problems.
How i may know the [x] for each clint? Sort it? and what if I will need to add new Company?
Is $set will work if field 'ownedItems[x].company_id' does not exist?
May be I may check smth in IF/Else statement. With, for example, $exist, or $cond( for aggregation) selectors. But .find() always return a cursor (is it?), not true or false. So what may do? How may I use aggregation selectors? Like this:
Users.find({_id: userId}, {$cond: [{$eq: ['owenedItem[x].company_id', _someId_]}, {$set:{...}}, {$push: {...}}]})
Will it work?
Sounds like you want to use the $elemMatch operator in conjunction with the '$' positional operator:
http://docs.mongodb.org/manual/reference/operator/elemMatch/
http://docs.mongodb.org/manual/reference/operator/positional/
Let's take your example. Let's say you want to find the element in the user's "ownedItems" list where the "company_id" is 3, and update that element's "item_amount" by 5. That can be done in a single update statement like so:
Users.update( { userId: _id, ownedItems : { $elemMatch : { company_id : 3 } } },
{ $inc : { ownedItems.$.item_amount : 5 } } )
The $elemMatch operator makes it explicit which of the elements of the list you're querying for. You can then use the $ operator in the modifier clause to refer to that matched element and make changes to it.
If the "ownedItems" list of the user does not have any entry matching { "company_id" : 3 } then the above update will not do anything. If that happens, you can do a second update with the $addToSet operator to add a new entry like so:
Users.update( { userId: _id },
{ $addToSet : { ownedItems : { company_id : 3, item_amount : 5 } } } )
http://docs.mongodb.org/manual/reference/operator/addToSet/