De acordo com a documentação do mongoldb , uma combinação dedistinct
Localiza os valores distintos para um campo especificado em uma única coleção ou exibição e retorna os resultados em uma matriz.
e operações de coleta de índices são o que retornaria todos os valores possíveis para uma determinada chave ou índice:
Retorna uma matriz que contém uma lista de documentos que identificam e descrevem os índices existentes na coleção
Portanto, em um determinado método, poderia-se usar um método como o seguinte, para consultar uma coleção por todos os seus índices registrados e retornar, digamos, um objeto com os índices das chaves (este exemplo usa async / waitit para NodeJS, mas obviamente, você poderia usar qualquer outra abordagem assíncrona):
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;
}
}
}
Portanto, consultar uma coleção com o _id
índice básico retornaria o seguinte (a coleção de teste possui apenas um documento no momento do teste):
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..
})
});
Lembre-se, isso usa métodos nativos para o driver NodeJS. Como algumas outras respostas sugeriram, existem outras abordagens, como a estrutura agregada. Pessoalmente, acho essa abordagem mais flexível, pois você pode criar e ajustar com facilidade como retornar os resultados. Obviamente, isso aborda apenas atributos de nível superior, não aninhados. Além disso, para garantir que todos os documentos sejam representados, caso haja índices secundários (que não sejam o principal _id), esses índices devem ser definidos como required
.