Ste*_*eve 301 mongodb mongodb-query aggregation-framework
我想获取MongoDB集合中所有键的名称.
例如,从这个:
db.things.insert( { type : ['dog', 'cat'] } );
db.things.insert( { egg : ['cat'] } );
db.things.insert( { type : [] } );
db.things.insert( { hello : [] } );
Run Code Online (Sandbox Code Playgroud)
我想得到独特的钥匙:
type, egg, hello
Run Code Online (Sandbox Code Playgroud)
kri*_*ina 323
您可以使用MapReduce执行此操作:
mr = db.runCommand({
"mapreduce" : "my_collection",
"map" : function() {
for (var key in this) { emit(key, null); }
},
"reduce" : function(key, stuff) { return null; },
"out": "my_collection" + "_keys"
})
Run Code Online (Sandbox Code Playgroud)
然后在生成的集合上运行distinct,以便找到所有键:
db[mr.result].distinct("_id")
["foo", "bar", "baz", "_id", ...]
Run Code Online (Sandbox Code Playgroud)
小智 196
以Kristina的答案为灵感,我创建了一个名为Variety的开源工具,它正是这样做的:https://github.com/variety/variety
use*_*814 52
您可以使用聚集新$objectToArrray的3.4.4版本所有顶级密钥值对转换成文件阵列,然后$unwind与$group 用$addToSet得到跨越整个集合不同的键.
$$ROOT 用于引用顶级文档.
db.things.aggregate([
{"$project":{"arrayofkeyvalue":{"$objectToArray":"$$ROOT"}}},
{"$unwind":"$arrayofkeyvalue"},
{"$group":{"_id":null,"allkeys":{"$addToSet":"$arrayofkeyvalue.k"}}}
])
Run Code Online (Sandbox Code Playgroud)
您可以使用以下查询来获取单个文档中的键.
db.things.aggregate([
{"$project":{"arrayofkeyvalue":{"$objectToArray":"$$ROOT"}}},
{"$project":{"keys":"$arrayofkeyvalue.k"}}
])
Run Code Online (Sandbox Code Playgroud)
小智 19
试试这个:
doc=db.thinks.findOne();
for (key in doc) print(key);
Run Code Online (Sandbox Code Playgroud)
小智 14
如果您的目标集合不是太大,您可以在mongo shell客户端下尝试:
var allKeys = {};
db.YOURCOLLECTION.find().forEach(function(doc){Object.keys(doc).forEach(function(key){allKeys[key]=1})});
allKeys;
Run Code Online (Sandbox Code Playgroud)
使用python.返回集合中所有顶级键的集合:
#Using pymongo and connection named 'db'
reduce(
lambda all_keys, rec_keys: all_keys | set(rec_keys),
map(lambda d: d.keys(), db.things.find()),
set()
)
Run Code Online (Sandbox Code Playgroud)
使用pymongo清理并重用的解决方案:
from pymongo import MongoClient
from bson import Code
def get_keys(db, collection):
client = MongoClient()
db = client[db]
map = Code("function() { for (var key in this) { emit(key, null); } }")
reduce = Code("function(key, stuff) { return null; }")
result = db[collection].map_reduce(map, reduce, "myresults")
return result.distinct('_id')
Run Code Online (Sandbox Code Playgroud)
用法:
get_keys('dbname', 'collection')
>> ['key1', 'key2', ... ]
Run Code Online (Sandbox Code Playgroud)
以下是在Python中使用的示例:此示例以内联方式返回结果.
from pymongo import MongoClient
from bson.code import Code
mapper = Code("""
function() {
for (var key in this) { emit(key, null); }
}
""")
reducer = Code("""
function(key, stuff) { return null; }
""")
distinctThingFields = db.things.map_reduce(mapper, reducer
, out = {'inline' : 1}
, full_response = True)
## do something with distinctThingFields['results']
Run Code Online (Sandbox Code Playgroud)
我认为这里提到的最好的方法是在 mongod 3.4.4+ 中,但不使用$unwind运算符并且只使用管道中的两个阶段。相反,我们可以使用$mergeObjectsand$objectToArray运算符。
在$group阶段,我们使用$mergeObjects运算符返回单个文档,其中键/值来自集合中的所有文档。
然后是$project我们使用$map和$objectToArray返回密钥的地方。
let allTopLevelKeys = [
{
"$group": {
"_id": null,
"array": {
"$mergeObjects": "$$ROOT"
}
}
},
{
"$project": {
"keys": {
"$map": {
"input": { "$objectToArray": "$array" },
"in": "$$this.k"
}
}
}
}
];
Run Code Online (Sandbox Code Playgroud)
现在如果我们有一个嵌套的文档并且想要获取密钥,这是可行的。为简单起见,让我们考虑一个带有简单嵌入文档的文档,如下所示:
{field1: {field2: "abc"}, field3: "def"}
{field1: {field3: "abc"}, field4: "def"}
Run Code Online (Sandbox Code Playgroud)
以下管道产生所有键(field1、field2、field3、field4)。
let allFistSecondLevelKeys = [
{
"$group": {
"_id": null,
"array": {
"$mergeObjects": "$$ROOT"
}
}
},
{
"$project": {
"keys": {
"$setUnion": [
{
"$map": {
"input": {
"$reduce": {
"input": {
"$map": {
"input": {
"$objectToArray": "$array"
},
"in": {
"$cond": [
{
"$eq": [
{
"$type": "$$this.v"
},
"object"
]
},
{
"$objectToArray": "$$this.v"
},
[
"$$this"
]
]
}
}
},
"initialValue": [
],
"in": {
"$concatArrays": [
"$$this",
"$$value"
]
}
}
},
"in": "$$this.k"
}
}
]
}
}
}
]
Run Code Online (Sandbox Code Playgroud)
只需稍加努力,我们就可以获得数组字段中所有子文档的键,其中元素也是对象。
如果您使用的是mongodb 3.4.4及更高版本,则可以使用$objectToArray和$group聚合来使用以下聚合
db.collection.aggregate([
{ "$project": {
"data": { "$objectToArray": "$$ROOT" }
}},
{ "$project": { "data": "$data.k" }},
{ "$unwind": "$data" },
{ "$group": {
"_id": null,
"keys": { "$addToSet": "$data" }
}}
])
Run Code Online (Sandbox Code Playgroud)
这是工作示例
我很惊讶,这里没有人通过使用简单javascript和Set逻辑来自动过滤重复值,mongo shell上的简单示例如下:
var allKeys = new Set()
db.collectionName.find().forEach( function (o) {for (key in o ) allKeys.add(key)})
for(let key of allKeys) print(key)
Run Code Online (Sandbox Code Playgroud)
这将打印集合名称中所有可能的唯一键:collectionName。
| 归档时间: |
|
| 查看次数: |
176674 次 |
| 最近记录: |