Delete documents from collection based on condition - mongodb

I want to delete the documents from a collection(Collection1) which are not matching with other collection(Collection2).
collection1 document - {_id: <autogen>, items: [{key:'key', ...}}]
collection2 document - {_id: 'key', action: {key1:'key1', ...}}, {_id: 'non_matching_key', action: {key1:'key1', ...}}
Delete all the documents from collection2, where items.key in collection1 is not matching with _id in collection2. with reference to the above example, a document with key-value 'non_matching_key' should be delete from collection2. There would be similar documents in collection2 like the one with _id value 'non_matching_key'.
The approach I thought was for mark and sweep.
I will add the column in collection2 documents for matching ids(in collection2 with items.key in collection1). This is mark step
Delete all the documents from collection2 where newly added column do not exists. This is sweep step.
Could you please advise if there is a better way of doing this?
Thanks,

Not fully clear how your documents look like and what are the exact conditions, but you could do it like this:
var ids = db.collection1.find({}, { "item.key": 1 }).toArray();
db.collection2.deleteMany({ _id: { $nin: ids } });

So basically, you want to iterate over your collection 2 and get all the ids that are not in collection 1 and delete those or vice versa.
db.collection2.find({}).forEach((doc) => db.collection1.deleteOne({_id: {$ne: doc._id}}))
or
let idsToDelete = db.collection2.find({}).distinct('_id')
let deleteResponse = db.collection1.deleteMany({_id: {$nin: idsToDelete}})
SWAP the collection name in the case of the other way.
NOTE: The code is just to give an overview and is not tested.

Related

Push values in Mongo Nested Array

enter image description here
Let's say that we have many documents like this in the photo
I have the above schema. I want to find the document based on _id first and then push an array of values to providedServices which belongs to the _id which is inside barbers array
A little help. Can't seem to find this out!
You need to find the related arrays firstly. For this, you can use $elemMatch or write it as 'barbers._id' : {$elemMatch: parameter}' .
Here we tried to find document with filtering it's own id and barbers id. You can change the filter as you wished. It can be only search on barbers id.
Need to write your DocumentName and your parameters instead of idValue, barbersId, serviceModel.
const result = await DocumentName.findOneAndUpdate(
{
$and:
[
{_id: mongoose.Types.ObjectId(idValue)},
{'barbers': {$elemMatch: {_id: mongoose.Types.ObjectId(barbersId)}}}
]
},
{ $push: { 'barbers.$.providedServices': serviceModel } },
{ new: true })
At first, we found the related barbers array inside of all documents. Then we pushed the model inside of providedServices array into this barbers array.

Adding a new subfield to a field of all documents in MongoDB

{
"_id":{"$oid":"5d6eb64a2a33670cfe44813f"},
"customer":"ddd",
"owners": { "a":"nnn", "b":"mmm"},
}
I have multiple documents in my MongoDB collection that look like above.
I want to be able to add a new field inside the owners to all documents.
For example, if I want to add "c" to the owners of all documents, how can I do that?
I found a query that does something like this:
db.myCollection.update({}, {$set: {"isOpen": false}}, false, true)
But I can I add a new sub-field ("c") to one of the fields ("owners") of my document?
Also tried,
db.profiles.update_many({}, { '$set': {'owners': {'c': ''}}})
but this removes the existing subfields and adds itself.
You are almost there. Just need to add the parent to the $set:
db.profiles.update_many({},{$set: {"owners.c": "something"}});
I guess you should remove $set, set overwrites an existing document

Query in mongodb mongoose

There is a database on mongodb. It contains a collection of products, which was created when importing from a csv file with a unique _id. In products, each document has a field articul corresponding to the article of the manufacturer. There is also a field size indicating the size of the product. Since the size of one product can be different, when you import documents are created which for the same articul will have different size.
How to make a selection from products and create another collection in which to put values with a unique articul that must contain all the values of size for each articul?
What you are looking for is aggregation. You can group the documents on article names and save it in a different collection
db.products.aggregate(
{$group: {_id: '$articul', sizes: {$addToSet: '$size'}}},
{$out: 'articles'}
)
To store new size for existed articul
db.products.update(
{ "articul": "Banana" },
{ $addToSet: { size: 9 } }
)
if nothing matched from above query you need create new insert query
db.products.insertOne({
"articul": "Apple", "size": [8]
});

Why is my MongoDb query inserting an embedded document on Update?

This is my MongoDB query:
db.events.update({date:{$gte: ISODate("2014-09-01T00:00:00Z")}},{$set:{"artists.$.soundcloud_toggle":false}},{multi:true,upsert:false})
Apparently I cannot use "artists.$.soundcloud_toggle" to update all artist documents within the artists array:
"The $ operator can update the first array element that matches
multiple query criteria specified with the $elemMatch() operator.
http://docs.mongodb.org/manual/reference/operator/update/positional/"
I'm happy to run the query a number of times changing the index of the array in order to set the soundcloud_toggle property of every artist in every event that matches the query e.g
artists.0.soundcloud_toggle
artists.1.soundcloud_toggle
artists.2.soundcloud_toggle
artists.3.soundcloud_toggle
The problem is: when there is say, only one artist document in the artists array and I run the query with "artists.1.soundcloud_toggle" It will insert an artist document into the artist array with a single property:
{
"soundcloud_toggle" : true
},
(I have declared "upsert:false", which should be false by default anyways)
How do I stop the query from inserting a document and setting soundcloud_toggle:false when there is no existing document there? I only want it to update the property if an artist exists at the given artists array index.
If, like you said, you don't mind completing the operation with multiple queries, you can add an $exists condition to your filter.
E.g. in the 5th iteration, when updating index=4, add: "artists.4": {$exists: true}, like:
db.events.update(
{ date: {$gte: ISODate("2014-09-01T00:00:00Z")},
"artists.4": {$exists: true} },
{ $set:{ "artists.4.soundcloud_toggle" :false } },
{ multi: true, upsert: false }
)

Mongodb find wrong document

You can see my document as bellow. How can I write a find for my uniq fields?
I need search a document where KEYMAP is (SNUM="3151" and "SKEY"="THR" and "SID"="ID_HUT")
{
"CID":"2",
"DESCRIPTION":"test",
"SECKEY":"test",
"API":{
"SMS":"http://api.php",
"DR":"http://api2.php"
},
"LOGS":{
"IN":"log_cid_in_1",
"OUT": "log_cid_out_1"
},
"KEYMAP":[
{"SNUM":"3151","SKEY":"THR", "SID":"ID_HUT"},
{"SNUM":"3152","SKEY":"ONE", "SID":"ID_XL"},
{"SNUM":"3153","SKEY":"TWO", "SID":"ID_INDO"}
]
}
db.content_provider_map.ensureIndex({"KEYMAP.SNUM":1,"KEYMAP.SKEY":1,"KEYMAP.SID":1},{unique:true});
db.mycollection.find({"KEYMAP.SNUM":"3151","KEYMAP.SKEY":"TWO","KEYMAP.SID":"ID_XL"});# not work. it find the document
I believe you want to use $elemMatch ( http://docs.mongodb.org/manual/reference/operators/#_S_elemMatch ) here like:
find({KEYMAP: {$elemMatch: {SNUM: "3151", SKEY: "TWO", SID: "ID_XL"}}})
Also unique indexes on subdocuments do not work the way you probably think they do. They create uniqueness across all documents not just that one document. If you want a unique index on that one document then you will need to use something like $addToSet or an upsert function on the subdocument.