Согласно документации mongoldb , комбинацияdistinct
Находит отдельные значения для указанного поля в одной коллекции или представлении и возвращает результаты в массиве.
и операции сбора индексов - это то, что возвращает все возможные значения для данного ключа или индекса:
Возвращает массив, содержащий список документов, которые идентифицируют и описывают существующие индексы в коллекции.
Таким образом, в данном методе можно использовать метод, подобный следующему, для запроса коллекции для всех ее зарегистрированных индексов и возврата, скажем, объекта с индексами для ключей (в этом примере используется async / await для NodeJS, но очевидно, вы можете использовать любой другой асинхронный подход):
async function GetFor(collection, index) {
let currentIndexes;
let indexNames = [];
let final = {};
let vals = [];
try {
currentIndexes = await collection.indexes();
await ParseIndexes();
//Check if a specific index was queried, otherwise, iterate for all existing indexes
if (index && typeof index === "string") return await ParseFor(index, indexNames);
await ParseDoc(indexNames);
await Promise.all(vals);
return final;
} catch (e) {
throw e;
}
function ParseIndexes() {
return new Promise(function (result) {
let err;
for (let ind in currentIndexes) {
let index = currentIndexes[ind];
if (!index) {
err = "No Key For Index "+index; break;
}
let Name = Object.keys(index.key);
if (Name.length === 0) {
err = "No Name For Index"; break;
}
indexNames.push(Name[0]);
}
return result(err ? Promise.reject(err) : Promise.resolve());
})
}
async function ParseFor(index, inDoc) {
if (inDoc.indexOf(index) === -1) throw "No Such Index In Collection";
try {
await DistinctFor(index);
return final;
} catch (e) {
throw e
}
}
function ParseDoc(doc) {
return new Promise(function (result) {
let err;
for (let index in doc) {
let key = doc[index];
if (!key) {
err = "No Key For Index "+index; break;
}
vals.push(new Promise(function (pushed) {
DistinctFor(key)
.then(pushed)
.catch(function (err) {
return pushed(Promise.resolve());
})
}))
}
return result(err ? Promise.reject(err) : Promise.resolve());
})
}
async function DistinctFor(key) {
if (!key) throw "Key Is Undefined";
try {
final[key] = await collection.distinct(key);
} catch (e) {
final[key] = 'failed';
throw e;
}
}
}
Таким образом, запрос коллекции с базовым _id
индексом вернет следующее (тестовая коллекция имеет только один документ на момент теста):
Mongo.MongoClient.connect(url, function (err, client) {
assert.equal(null, err);
let collection = client.db('my db').collection('the targeted collection');
GetFor(collection, '_id')
.then(function () {
//returns
// { _id: [ 5ae901e77e322342de1fb701 ] }
})
.catch(function (err) {
//manage your error..
})
});
Имейте в виду, это использует методы, родные для драйвера NodeJS. Как предлагали некоторые другие ответы, существуют и другие подходы, такие как совокупная структура. Лично я нахожу этот подход более гибким, так как вы можете легко создавать и настраивать способы возврата результатов. Очевидно, что это касается только атрибутов верхнего уровня, а не вложенных. Кроме того, чтобы гарантировать, что все документы представлены, если есть вторичные индексы (кроме основного _id), эти индексы должны быть установлены как required
.