2017-11-21 186 views
5

Szukam pętli kwerendy za pośrednictwem różnych kolekcji z MongoDB przy użyciu NodeJS Driver. Do tego testu, Użyłem sample code from the 'findOne' docs wstawić kilka dokumentów w różnych kolekcji:NodeJS/Mongo: Pętla kwerendy za pośrednictwem różnych kolekcji

collection.insertMany([{a:1, b:1}, {a:2, b:2}, {a:3, b:3}], {w:1}, function(err, result) { 
    test.equal(null, err); 

Tworzenie w tym samym czasie różnych kolekcjach (każda kolekcja ma co najmniej jedno wystąpienie dokumentów uprzednio włożona):

  • Test 1 Test
  • test2
  • test3
  • test4
  • test6
  • test10

I co chcę zebrać listę kolekcji, które mam w DB ('test' w moim przypadku):

var MongoClient = require("mongodb").MongoClient, 
    test = require("assert"); 
MongoClient.connect("mongodb://localhost:27017/test", function(err, db) { 
    db.listCollections().toArray(function(err, items) { 
    test.ok(items.length >= 1); 
    console.log(items); 
    db.close(); 
    }); 
}); 

i tam wyskakuje lista wcześniej wspomnianych kolekcji. Do tej pory wszystko jest w porządku! Mogę nawet przejrzeć tablicę, aby uzyskać nazwę tylko kolekcji:

var MongoClient = require("mongodb").MongoClient, 
    test = require("assert"); 
MongoClient.connect("mongodb://localhost:27017/test", function(err, db) { 
    db.listCollections().toArray(function(err, items) { 
    test.ok(items.length >= 1); 
    items.forEach(c => { 
     console.log(c.name); 
    }); 
    db.close(); 
    }); 
}); 

Znowu nie ma problemu! Ale kiedy spróbuj zapytania w pętli:

var MongoClient = require("mongodb").MongoClient, 
    test = require("assert"); 
MongoClient.connect("mongodb://localhost:27017/test", function(err, db) { 
    db.listCollections().toArray(function(err, items) { 
    test.ok(items.length >= 1); 
    items.forEach(c => { 
     var collection = db.collection(c.name); 
     collection.findOne({ a: 2 }, { fields: { b: 1 } }, function(err, doc) { 
     console.log(doc); 
     }); 
    }); 
    }); 
    db.close(); 
}); 

uzyskać:

null 
null 
null 
null 
null 
null 
null 

Nawet przelotowego uzyskać kolekcji wydaje się działać perfekcyjnie:

var MongoClient = require("mongodb").MongoClient, 
    test = require("assert"); 
MongoClient.connect("mongodb://localhost:27017/test", function(err, db) { 
    db.listCollections().toArray(function(err, items) { 
    test.ok(items.length >= 1); 
    items.forEach(c => { 
     var collection = db.collection(c.name); 
     console.log(collection); 
     }); 
    }); 
    db.close(); 
}); 

Przykład wyjście:

Collection { 
    s: 
    { pkFactory: 
     { [Function: ObjectID] 
     index: 10866728, 
     createPk: [Function: createPk], 
     createFromTime: [Function: createFromTime], 
     createFromHexString: [Function: createFromHexString], 
     isValid: [Function: isValid], 
     ObjectID: [Circular], 
     ObjectId: [Circular] }, 
    db: 
     Db { 
     domain: null, 
     _events: {}, 
     _eventsCount: 0, 
     _maxListeners: undefined, 
     s: [Object], 
     serverConfig: [Getter], 
     bufferMaxEntries: [Getter], 
     databaseName: [Getter] }, 
    topology: 
     Server { 
     domain: null, 
     _events: [Object], 
     _eventsCount: 8, 
     _maxListeners: undefined, 
     clientInfo: [Object], 
     s: [Object] }, 
    dbName: 'test', 
    options: 
     { promiseLibrary: [Function: Promise], 
     readConcern: undefined, 
     readPreference: [Object] }, 
    namespace: 'test.test2', 
    readPreference: 
     ReadPreference { 
     _type: 'ReadPreference', 
     mode: 'primary', 
     tags: undefined, 
     options: undefined }, 
    slaveOk: true, 
    serializeFunctions: undefined, 
    raw: undefined, 
    promoteLongs: undefined, 
    promoteValues: undefined, 
    promoteBuffers: undefined, 
    internalHint: null, 
    collectionHint: null, 
    name: 'test2', 
    promiseLibrary: [Function: Promise], 
    readConcern: undefined } } 

Zgaduję, że struktura Collection jest problem dla mojej pętli, ale nie jestem pewien, co dokładnie się dzieje ... To jest przykład oczekiwanego wyjścia dla każdej kolekcji:

{ _id: 5a13de85a55e615235f71528, b: 2 } 

Każda pomoc będzie być docenionym! Z góry dziękuję!

Odpowiedz

1

choć nie najlepszy składni i bezużyteczny wyjątkiem zalogowaniu wyjście, to działa na ja:

var mongodb = require('mongodb'); 


mongodb.connect('mongodb://localhost:27017/test', function (err, db) { 
    if (err) { 
     throw err; 
    } 

    db.listCollections().toArray(function (err, cols) { 
     if (err) { 
      throw err; 
     } 

     cols.forEach(function (col) { 
      db.collection(col.name).find({}, {}, 0, 1, function (err, docs) { 
       if(err){ 
        throw err; 
       } 
       console.log(col); 
       docs.forEach(console.log); 
      }); 
     }); 
    }) 
}) 

Być może warunki zapytania nie pasują do niczego?

Również lepiej obietnicami:

const mongodb = require('mongodb'); 
const Promise = require('bluebird'); 

function getDb() { 
    return Promise.resolve(mongodb.connect('mongodb://localhost:27017/test')); 
} 

function getCollections(db) { 
    return Promise.resolve(db.listCollections().toArray()); 
} 

function getDocs(db, col) { 
    return Promise.resolve(db.collection(col.name).find({},{},0,1).toArray()); 
} 

const data = {}; 
getDb() 
.then((db) => { 
    data.db = db; 
    return getCollections(db); 
}).then((cols) => { 
    data.cols = cols; 
    return Promise.map(cols, (col) => getDocs(data.db,col)); 
}).then((docs) => { 
    console.log(docs); 
}) 
+0

Hej SD! Nie w pełni przetestowałem twoje rozwiązanie, ale wydaje się, że ouptup jest poprawny! Dzięki za pomoc! : P – Ardzii

+0

Hej znowu S.D.! Masz część odpowiedzi ... Mam na myśli, że twój kod działa idealnie dla znalezienia i kiedy próbuję dostać findOne dostaję "TypeError: docs.forEach nie jest funkcją" i naprawdę nie rozumiem, dlaczego uzyskać TypeError na funkcji, która nie została nawet zmodyfikowana ...? : S – Ardzii

+1

@Ardzii findOne nie zwraca tablicy, ale pojedynczy dokument. Tak więc, dla każdego nie jest potrzebny do jednego dokumentu. –

1

ForEach pętla w javaScript jest synchroniczna, dopóki nie zawiera żadnych połączeń asynchronicznych. W tym przypadku nie można wywołać żadnego połączenia DB w pętli for.

Zamiast tego można użyć biblioteki o nazwie asynchronicznie, która pochodzi z fantastycznych funkcji zająć się tym problemem, jak poniżej

var MongoClient = require("mongodb").MongoClient, 
    test = require("assert"), 
    async = require('async'); 
MongoClient.connect("mongodb://localhost:27017/test", function (err, db) { 
db.listCollections().toArray(function (err, items) { 
    test.ok(items.length >= 1); 

    async.map(items, (each, callback) => { 
     let collection = db.collection(each.name); 
     collection.findOne({a: 2}, {fields: {b: 1}}, function (err, doc) { 
      console.log(doc); 
      callback(); 
     }); 
    }, (err) => { 
     console.log("done"); 
    }); 
    }); 
    db.close(); 
}); 
+0

Hej Rohan! Dzięki za odpowiedź, nadal otrzymuję wartość null, null, null, ..., done. – Ardzii

+0

Nie ma innych prób? : P – Ardzii

+1

hej Ardzil, czy możesz użyć funkcji collection.findOne ({a: 2}, {b: 1}, funkcji (err, doc) { console.log (doc); callback(); }); –