Need to delete mongodb collection with prefix based name - mongodb

I have number of collection in my mongodb.
The collections names are like aaa_123,aaa_345,aaa_ccc,mmm,nnn and etc...
Many collections name has prefixed with aaa_ and also other collection name also present, I need to delete only the collection names prefixed with aaa_ , but in manual I deleted like db.aaa_123.drop(), its take long time to delete collection , Is there anyway to delete all collections with prefixed aaa_ in mongodb?
Anyhelp appreciated..

First Get all collection in DB to one variable then loop through that variable and check for that name in collection. If that check condition satisfies delete that collection. Check below for code sample
var collectionNames = db.getCollectionNames();
for(var i = 0, len = collectionNames.length; i < len ; i++){
var collectionName = collectionNames[i];
if(collectionName.indexOf('aaa_') == 0){
db[collectionName].drop()
}
}
Hope this helps

Related

Convert all collection in a single db into new dbs

can you please help me,
I am trying to copy all collections in a particular database into create new database and move that collection into it.But the following code does not work. and my colleciton name in the db contains two part ' mg2.data' ,'mg32.data' i want to create new database mg2 and copy collection name as data.
collection name mg2.data suppose to be in mg2 database and collection name data.
db.getCollectionNames().forEach(function( a ){
if(a!='system.indexes' ) {
var sp = a.split('.');
var dbName = sp[0];
var col = sp[1];
//print(dbName)
db[a].copyTo(db.getSiblingDB(dbName).getcCollection(col));
}
});
Here is my situation details.
I am having Db name Master and it contains about 60-70 collections its names like(mg1.data,mg2.data,mg3.data)
and i want it to be like
db name mg1 and collection name data
db name mg2 and collection name data and so on..
i am facing the problem that when in the first design write operation locks entire database(Master). i cannot go for sharding and all now.
I got this approach working for me.I dont know is this best aproach
db.getCollectionNames().forEach(function( a ){
if(a!='system.indexes' ) {
var sp = a.split('.');
var dbName = sp[0];
var col = sp[1];
print(dbName+'\n');
//db[a].copyTo(db.getSiblingDB(dbName).getcCollection(col));
db[a].find().forEach(function(d){ db.getSiblingDB(dbName)[col].insert(d); });
}
});

Composite views in couchbase

I'm new to Couchbase and am struggling to get a composite index to do what I want it to. The use-case is this:
I have a set of "Enumerations" being stored as documents
Each has a "last_updated" field which -- as you may have guessed -- stores the last time that the field was updated
I want to be able to show only those enumerations which have been updated since some given date but still sort the list by the name of the enumeration
I've created a Couchbase View like this:
function (doc, meta) {
var time_array;
if (doc.doc_type === "enum") {
if (doc.last_updated) {
time_array = doc.last_updated.split(/[- :]/);
} else {
time_array = [0,0,0,0,0,0];
}
for(var i=0; i<time_array.length; i++) { time_array[i] = parseInt(time_array[i], 10); }
time_array.unshift(meta.id);
emit(time_array, null);
}
}
I have one record that doesn't have the last_updated field set and therefore has it's time fields are all set to zero. I thought as a first test I could filter out that result and I put in the following:
startkey = ["a",2012,0,0,0,0,0]
endkey = ["Z",2014,0,0,0,0,0]
While the list is sorted by the 'id' it isn't filtering anything! Can anyone tell me what I'm doing wrong? Is there a better composite view to achieve these results?
In couchbase when you query view by startkey - endkey you're unable to filter results by 2 or more properties. Couchbase has only one index, so it will filter your results only by first param. So your query will be identical to query with:
startkey = ["a"]
endkey = ["Z"]
Here is a link to complete answer by Filipe Manana why it can't be filtered by those dates.
Here is a quote from it:
For composite keys (arrays), elements are compared from left to right and comparison finishes as soon as a element is different from the corresponding element in the other key (same as what happens when comparing strings à la memcmp() or strcmp()).
So if you want to have a view that filters by date, date array should go first in composite key.

How does Mongoengine decide if 2 EmbeddedDocuments are equal or not?

I have the following Mongoengine document:
class MyEmbed(EmbeddedDocument):
embedField = StringField(primary_key=True)
varField = StringField()
class TestDoc(Document):
myField = StringField()
embed_list = ListField(EmbeddedDocumentField(MyEmbed))
So I keep a list of embedded documents, to which I wish to add new documents if they don't exist already. The problem is that when I use the atomic update operator add_to_set things don't turn out the way I want them to.
This is what I am trying to do:
embed1 = models.MyEmbed(embedField="F1")
parent = models.TestDoc(myField="ParentField")
embed_list = []
embed_list.append(embed1)
parent.embed_list = embed_list
parent.save()
embed2 = models.MyEmbed(embedField="F1", varField="varField")
TestDoc.objects(id=parent.id).update_one(add_to_set__embed_list=embed2)
The problem is that after doing this, I have in the DB a list of embedded documents with 2 elements. And what I want is to decide upon one field (embedField in this case) whether 2 EmbeddedDocuments are equal or not, and not by taking into account all the properties. My questions are:
What are the default criteria according to which Mongoengine decides whether 2 EmbeddedDocuments are equal or not?
How can I redefine the function that makes Mongoengine decide when 2 EmbeddedDocuments are equal or not?
Thanks!
The actual checking is done inside MongoDB and not mongoengine.
The object sent to mongodb should be the same, but this is where it gets tricky as with BSON order is important and in python with dictionaries its not. When converting to send to mongodb mongoengine just passes a dictionary. This is a bug - so I've added #296 and will fix for 0.8
See https://github.com/MongoEngine/mongoengine/blob/master/mongoengine/document.py#L51 and https://github.com/MongoEngine/mongoengine/blob/master/mongoengine/base/document.py#L52:
def __eq__(self, other):
if isinstance(other, self.__class__):
return self._data == other._data
return False
It compare dicts of Embedded documents data. So you can override this method.
If you look at Document update that calls QuerySet update (find add_to_set and addToSet) you can find that mongoengine doesnt't check exists document in list and just call mongo $addToSet operation: https://github.com/MongoEngine/mongoengine/blob/master/mongoengine/queryset/transform.py#L156.
In your code you have document MyEmbed(embedField="F1") and try add another document MyEmbed(embedField="F1", varField="varField") so logic right: it add new document. If you try next code:
embed1 = models.MyEmbed(embedField="F1")
parent = models.TestDoc(myField="ParentField")
embed_list = []
embed_list.append(embed1)
parent.embed_list = embed_list
parent.save()
embed2 = models.MyEmbed(embedField="F1", varField="varField")
TestDoc.objects(id=parent.id).update_one(add_to_set__embed_list=embed2)
embed3 = models.MyEmbed(embedField="F1")
TestDoc.objects(id=parent.id).update_one(add_to_set__embed_list=embed3)
embed4 = models.MyEmbed(embedField="F1", varField="varField")
TestDoc.objects(id=parent.id).update_one(add_to_set__embed_list=embed4)
you can find that parent contains only embed1 and embed2.
So, to resolve you problem you can override __eq__ method and check document in list, but you must find another solution for update document list, because it have direct call of mongo method.

Remove records from Mongodb using shell

I have a simple collection populated with student data and I need to remove some records based on some parameters. I executed the following from mongoshell
for(i=0;i<200;i++) {
var rec = db.grades.find({student_id:i,type:'homework'}).sort({score:1}).limit(1)
db.grades.remove(rec)
}
Ideally it should remove lowest score of type homework for all student_ids. Apparently, only the last 2 records (student_id: 199) from the find parameter was purged and the rest still exists.
db.grades.find({student_id:10,type:'homework'}).sort({score:1}).limit(1)
{ "_id" : ObjectId("50906d7fa3c412bb040eb5a1"), "student_id" : 10, "type" : "homework", "score" : 6.094174990746648 }
Is it because of the aysnchoronous nature of JS / Mongo ? What are the other alternatives for solving the same?
rec is not a document, it is a database cursor. You need to actually get a document from it:
for(i=0;i<200;i++) {
var cur = db.grades.find({student_id:i,type:'homework'}).sort({score:1}).limit(1);
var actualDoc = cur.next();
db.grades.remove(actualDoc);
}
Otherwise, you're trying to remove documents based on cursor properties, which is not what you want. See also http://docs.mongodb.org/manual/core/read-operations/#cursors.
You need to query the collection and return all of the documents in the collection first before iterating through it e.g.
var collection = grades.find({'type':'homework'}).sort({'student_id',1, 'score':1})
Then iterate through the records in the variable 'collection' removing documents with the lowest score. You also have an issue assigning i as a value to student_id without assigning the documents in the collection. And according to your code you're iterating through the collection based on student id. You don't need to do this to iterate through the collection. Just query all records of type homework then remove based on parameters. If you need to assign the value of student_id to a variable (hint: as a parameter to remove records), just assign student_id to a variable like so:
var id = ['student_id']
Alternatively (and this is the way I did it), you could sort all the records first by student_id and then by score. The score should be sorted in descending order.
Then iterate through the collection using a for loop, and when the student_id changes remove the record. To recognise the change in student_id store that value in a variable outside the loop and inside the loop (as 2 separate variables) then update them as you loop through the collection. Then compare the variables and remove the record if the values of the variables are not equal.
var oldid=-1;
var cursor=db.grades.find({'type':'homework'}).sort({'student_id':1,'score':1});
while (cursor.hasNext()) {
var doc = cursor.next();
var id = doc['student_id'];
if (oldid!=id)
{
db.grades.remove(doc);
oldid=id;
}
}

How do I get the date a MongoDB collection was created using MongoDB C# driver?

I need to iterate through all of the collections in my MongoDB database and get the time when each of the collections was created (I understand that I could get the timestamp of each object in the collection, but I would rather not go that route if a simpler/faster method exists).
This should give you an idea of what I'm trying to do:
MongoDatabase _database;
// code elided
var result = _database.GetAllCollectionNames().Select(collectionName =>
{
_database.GetCollection( collectionName ) //.{GetCreatedDate())
});
As far as I know, MongoDB doesn't keep track of collection creation dates. However, it's really easy to do this yourself. Add a simple method, something like this, and use it whenever you create a new collection:
public static void CreateCollectionWithMetadata(string collectionName)
{
var result = _db.CreateCollection(collectionName);
if (result.Ok)
{
var collectionMetadata = _db.GetCollection("collectionMetadata");
collectionMetadata.Insert(new { Id = collectionName, Created = DateTime.Now });
}
}
Then whenever you need the information just query the collectionMetadata collection. Or, if you want to use an extension method like in your example, do something like this:
public static DateTime GetCreatedDate(this MongoCollection collection)
{
var collectionMetadata = _db.GetCollection("collectionMetadata");
var metadata = collectionMetadata.FindOneById(collection.Name);
var created = metadata["Created"].AsDateTime;
return created;
}
The "creation date" is not part of the collection's metadata. A collection does not "know" when it was created. Some indexes have an ObjectId() which implies a timestamp, but this is not consistent and not reliable.
Therefore, I don't believe this can be done.
Like Mr. Gates VP say, there is no way using the metadata... but you can get the oldest document in the collection and get it from the _id.
Moreover, you can insert an "empty" document in the collection for that purpose without recurring to maintain another collection.
And it's very easy get the oldest document:
old = db.collection.find({}, {_id}).sort({_id: 1}).limit(1)
dat = old._id.getTimestamp()
By default, all collection has an index over _id field, making the find efficient.
(I using MongoDb 3.6)
Seems like it's some necroposting but anyway: I tried to find an answer and got it:
Checked it in Mongo shell, don't know how to use in C#:
// db.payload_metadata.find().limit(1)
ObjectId("60379be2bec7a3c17e6b662b").getTimestamp()
ISODate("2021-02-25T12:45:22Z")