var arrayOfFieldNames = [];
var items = db.NAMECOLLECTION.find();
while(items.hasNext()) {
var item = items.next();
for(var index in item) {
arrayOfFieldNames[index] = index;
}
}
for (var index in arrayOfFieldNames) {
print(index);
}
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;
}
}
}
18 回答
使用pymongo清理和重复使用的解决方案:
用法:
您可以使用MapReduce执行此操作:
然后在生成的集合上运行distinct,以便找到所有键:
以Kristina's answer为灵感,我创建了一个名为Variety的开源工具,它正是这样做的:https://github.com/variety/variety
您可以使用3.4.4版本中的新$objectToArrray聚合将所有顶部键和值对转换为文档数组,然后将$unwind&$group转换为$addToSet以在整个集合中获取不同的键 .
$$ROOT用于引用顶级文档 .
您可以使用以下查询来获取单个文档中的键 .
试试这个:
如果您的目标集合不是太大,您可以在mongo shell客户端下尝试:
使用python . 返回集合中所有顶级键的集合:
以下是在Python中使用的示例:此示例以内联方式返回结果 .
如果您使用的是mongodb 3.4.4及更高版本,则可以使用$objectToArray和$group聚合使用以下聚合
这是工作example
这对我来说很好:
要获取所有键的列表减去
_id
,请考虑运行以下聚合管道:我认为最好的方法是如上所述here在mongod 3.4.4中,但不使用
$unwind
运算符并且只使用管道中的两个阶段 . 相反,我们可以使用$mergeObjects和$objectToArray运算符 .在
$group
阶段,我们使用$mergeObjects
运算符返回单个文档,其中键/值来自集合中的所有文档 .然后是
$project
,我们使用$map
和$objectToArray
来返回键 .现在,如果我们有一个嵌套文档并且想要获取密钥,那么这是可行的 . 为简单起见,让我们考虑一个带有简单嵌入式文档的文档,如下所示:
以下管道产生所有键(field1,field2,field3,field4) .
稍加努力,我们就可以获得数组字段中所有子文档的键,其中元素也是对象 .
我试图在nodejs中写,最后想出了这个:
读取新创建的集合“allFieldNames”后,将其删除 .
根据mongoldb documentation,
distinct
的组合和indexes集合操作将返回给定键或索引的所有可能值:
所以在给定的方法中,可以使用类似下面的方法,以便查询集合中所有已注册的索引,并返回,例如带有键索引的对象(此示例使用async / await作为NodeJS,但是显然你可以使用任何其他异步方法):
因此,使用基本
_id
索引查询集合将返回以下内容(测试集合在测试时只有一个文档):请注意,这使用了NodeJS驱动程序的原生方法 . 正如其他一些答案所暗示的那样,还有其他方法,例如聚合框架 . 我个人认为这种方法更灵活,因为您可以轻松创建和微调如何返回结果 . 显然,这只能解决顶级属性,而不是嵌套属性 . 此外,为了保证所有文档都被表示,如果存在二级索引(主_id除外),则应将这些索引设置为
required
.也许稍微偏离主题,但你可以递归地漂亮打印对象的所有键/字段:
当集合中的所有对象具有相同的结构时很有用 .
我对Carlos LM的解决方案进行了一些扩展,因此它更加详细 .
架构示例:
输入控制台:
跑:
产量
我有一个更简单的工作...
你可以做的就是将数据/文档插入主集合“事物”必须在1个单独的集合中插入属性,让我们说“things_attributes” .
因此,每次插入“things”时,您都会从“things_attributes”获得该文档的值与新文档键的比较,如果有任何新键将其附加到该文档中并再次重新插入它 .
所以things_attributes将只有1个唯一键文档,您可以通过使用findOne()在需要时轻松获取这些文档