Перебрать все коллекции Mongo и выполнить запрос

Во-первых, я совсем новичок в mongodb. Вот мой вопрос, на который я не смог найти решение.

Допустим, у меня есть 3 разные коллекции.

mongos> show collections
collectionA
collectionB
collectionC

Я хочу создать сценарий, который выполняет итерацию по всем коллекциям в этой базе данных и находит последнюю вставленную отметку времени в каждой из этих коллекций. Вот что работает внутри mongos.

var last_element = db.collectionA.find().sort({_id:-1}).limit(1);
printjson(last_element.next()._id.getTimestamp());
ISODate("2014-08-28T06:45:47Z")

<сильный>1. Проблема (перебор всех коллекций)

Есть ли возможность что-л. подобно.

var my_collections = show collections;
my_collections.forEach(function(current_collection){
    print(current_collection);
});

Проблема здесь, назначение для my_collections не работает. Я получаю SyntaxError: Unexpected identifier. Нужно ли цитировать выражение «show»? Это вообще возможно?

<сильный>2. Проблема (сохранение коллекции в js var)

Я могу обойти проблему 1, выполнив следующие действия:

var my_collections = ["collectionA", "collectionB", "collectionC"];
my_collections.forEach(function(current_collection){
    var last_element = db.current_collection.find().sort({_id:-1}).limit(1);
    print(current_collection);
    printjson(last_element.next()._id.getTimestamp());
});

last_element.next() выдает следующую ошибку:

ошибка hasNext: false в src/mongo/shell/query.js:124

Кажется, что last_element не сохраняется правильно.

Любые предложения о том, что я делаю неправильно ??


ОБНОВЛЕНИЕ

Ответ Нила привел меня к этому решению. В дополнение к его коду я должен был проверить, действительно ли существует функция getTimestamp. Для некоторых «виртуальных» коллекций, похоже, нет свойства _id.

db.getCollectionNames().forEach(function(collname) {
    var last_element = db[collname].find().sort({_id:-1}).limit(1);
    if(last_element.hasNext()){
        var next = last_element.next();
        if(next._id !== undefined && typeof next._id.getTimestamp == 'function'){
           printjson(collname + " >> "+next._id.getTimestamp());
        }else{
          print(collname + " undefined!! (getTimestamp N/A)")
        }
    }
});

person cb0    schedule 28.08.2014    source источник
comment
Просто чтобы уточнить здесь. Единственная причина, по которой .getTimeStamp() здесь не сработает, заключается в том, что на самом деле у вас нет ObjectId в поле первичного ключа _id в каждом документе. Вы должны действительно посмотреть на это, как будто MongoDB позволит вам смешивать типы в полях, поскольку это не содержит схемы, вы не должны делать это как общую практику и действительно должны исправляя это там, где это происходит, чтобы сделать записи согласованными.   -  person Neil Lunn    schedule 01.09.2014
comment
Спасибо за это уведомление! Как уже говорилось, я новичок в монго и работаю с реляционными базами данных. Я до сих пор не понимаю, как были созданы эти коллекции и почему у них нет ObjectID. Как вы сказали, мне нужно исправить это и понять, почему и как. Спасибо!   -  person cb0    schedule 02.09.2014


Ответы (1)


Существует вспомогательный метод db.getCollectionNames(), который сделает это за вас. Затем вы можете реализовать свой код:

db.getCollectionNames().forEach(function(collname) {
    // find the last item in a collection
    var last_element = db[collname].find().sort({_id:-1}).limit(1);
    // check that it's not empty
    if (last_element.hasNext()) {
        // print its timestamp
        printjson(last_element.next()._id.getTimestamp());
    }
})

Возможно, вам также понадобится проверка .hasNext() для возможных пустых коллекций.

person Neil Lunn    schedule 28.08.2014
comment
Я бы сказал, что это действительно безопасно делать только в среде оболочки, где все вызовы синхронны; это решение в среде асинхронного драйвера рискованно (много параллельных запросов в быстрой последовательности). - person zamnuts; 01.09.2014
comment
@zamnuts Существует множество способов безопасно обрабатывать списки и потоки данных в асинхронной среде. Вам просто нужно знать об обратных вызовах, чтобы объявить о каждой итерации. Если вы не уверены в этом, вы всегда можете задать вопрос, и кто-нибудь, скорее всего, покажет вам, как это сделать. - person Neil Lunn; 01.09.2014