Según la documentación de mongoldb , una combinación dedistinct
Encuentra los valores distintos para un campo específico en una única colección o vista y devuelve los resultados en una matriz.
y las operaciones de recopilación de índices son las que devolverían todos los valores posibles para una clave o índice dado:
Devuelve una matriz que contiene una lista de documentos que identifican y describen los índices existentes en la colección.
Entonces, en un método dado, uno podría usar un método como el siguiente, para consultar una colección para todos sus índices registrados y regresar, digamos un objeto con los índices para las claves (este ejemplo usa async / await para NodeJS, pero obviamente, podría usar cualquier otro enfoque asincrónico):
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;
}
}
}
Entonces, consultar una colección con el _id
índice básico devolvería lo siguiente (la colección de prueba solo tiene un documento en el momento de la prueba):
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..
})
});
Eso sí, esto utiliza métodos nativos del controlador NodeJS. Como han sugerido algunas otras respuestas, existen otros enfoques, como el marco agregado. Personalmente, considero que este enfoque es más flexible, ya que puede crear y ajustar fácilmente cómo devolver los resultados. Obviamente, esto solo aborda los atributos de nivel superior, no los anidados. Además, para garantizar que todos los documentos estén representados en caso de que haya índices secundarios (que no sean el _id principal), esos índices deben establecerse como required
.