답변:
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"
})
그런 다음 결과 키에 대해 distinct를 실행하여 모든 키를 찾으십시오.
db[mr.result].distinct("_id")
["foo", "bar", "baz", "_id", ...]
for (var key in this.first_level.second_level.nth_level) { emit(key, null); }
db.runCommand({..., out: { "inline" : 1 }}).results.map(function(i) { return i._id; });
와 크리스티나의 대답 : 영감, 나는 정확히 수행 다양성이라는 오픈 소스 도구를 만들어 https://github.com/variety/variety을
당신은 새와 함께 집계를 사용할 수 있습니다 $objectToArrray
에서 3.4.4
다음 문서 배열에 모든 상위 키 및 값 쌍으로 변환 버전 $unwind
및 $group
로 $addToSet
전체 컬렉션에서 개별의 키를 얻을 수 있습니다.
$$ROOT
최상위 문서를 참조하십시오.
db.things.aggregate([
{"$project":{"arrayofkeyvalue":{"$objectToArray":"$$ROOT"}}},
{"$unwind":"$arrayofkeyvalue"},
{"$group":{"_id":null,"allkeys":{"$addToSet":"$arrayofkeyvalue.k"}}}
])
단일 문서에서 키를 얻기 위해 아래 쿼리를 사용할 수 있습니다.
db.things.aggregate([
{"$match":{_id: "5e8f968639bb8c67726686bc"}}, /* Replace with the document's ID */
{"$project":{"arrayofkeyvalue":{"$objectToArray":"$$ROOT"}}},
{"$project":{"keys":"$arrayofkeyvalue.k"}}
])
.next()["allkeys"]
컬렉션에 요소가 하나 이상 있다고 가정하면 명령에 추가 할 수 있습니다 .
이 시도:
doc=db.thinks.findOne();
for (key in doc) print(key);
대상 컬렉션이 너무 크지 않으면 mongo shell client에서 시도해 볼 수 있습니다.
var allKeys = {};
db.YOURCOLLECTION.find().forEach(function(doc){Object.keys(doc).forEach(function(key){allKeys[key]=1})});
allKeys;
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')
용법:
get_keys('dbname', 'collection')
>> ['key1', 'key2', ... ]
if (typeof(this[key]) == 'number')
before를 추가하십시오 emit(key, null)
.
파이썬 사용하기. 컬렉션의 모든 최상위 키 집합을 반환합니다.
#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()
)
다음은 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']
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" }
}}
])
작업 예 는 다음과 같습니다.
$match
집계 파이프 라인의 시작 부분에서 조건과 일치하는 문서의 키만 가져올 수도 있습니다 .
놀랍게도, 여기에 아무도 간단 javascript
하고 Set
논리를 사용 하여 중복 값을 자동으로 필터링하여 mongo 셸의 간단한 예를 아래에서 볼 수 있습니다.
var allKeys = new Set()
db.collectionName.find().forEach( function (o) {for (key in o ) allKeys.add(key)})
for(let key of allKeys) print(key)
컬렉션 이름에 가능한 모든 고유 키 를 인쇄합니다 : collectionName .
여기 에 언급 된 것처럼이 작업을 수행하는 가장 좋은 방법은 mongod 3.4.4 이상이지만 $unwind
연산자를 사용 하지 않고 파이프 라인에서 두 단계 만 사용 한다고 생각합니다 . 대신 $mergeObjects
and $objectToArray
연산자를 사용할 수 있습니다 .
이 $group
단계 에서는 $mergeObjects
연산자를 사용 하여 컬렉션의 모든 문서에서 키 / 값이있는 단일 문서를 반환합니다.
그런 다음 $project
우리가 사용 $map
하고 $objectToArray
키를 반환하는 곳 이옵니다.
let allTopLevelKeys = [
{
"$group": {
"_id": null,
"array": {
"$mergeObjects": "$$ROOT"
}
}
},
{
"$project": {
"keys": {
"$map": {
"input": { "$objectToArray": "$array" },
"in": "$$this.k"
}
}
}
}
];
중첩 된 문서가 있고 키를 얻으려면이 작업을 수행 할 수 있습니다. 간단하게하기 위해 다음과 같은 간단한 포함 문서가있는 문서를 고려하십시오.
{field1: {field2: "abc"}, field3: "def"}
{field1: {field3: "abc"}, field4: "def"}
다음 파이프 라인은 모든 키 (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"
}
}
]
}
}
}
]
약간의 노력으로 요소가 객체 인 배열 필드의 모든 하위 문서에 대한 키를 얻을 수 있습니다.
$unwind
수집 (필드 수 * 문서 수 없음)을 확장 $mergeObjects
하면 모든 버전> 을 사용하여이를 피할 수 있습니다 3.6
. -_-)
주제를 약간 벗어난 것일 수도 있지만 객체의 모든 키 / 필드를 재귀 적으로 인쇄 할 수 있습니다.
function _printFields(item, level) {
if ((typeof item) != "object") {
return
}
for (var index in item) {
print(" ".repeat(level * 4) + index)
if ((typeof item[index]) == "object") {
_printFields(item[index], level + 1)
}
}
}
function printFields(item) {
_printFields(item, 0)
}
컬렉션의 모든 객체가 동일한 구조를 가질 때 유용합니다.
모든 키 빼기의 목록을 얻으려면 _id
다음 집계 파이프 라인을 실행하십시오.
var keys = db.collection.aggregate([
{ "$project": {
"hashmaps": { "$objectToArray": "$$ROOT" }
} },
{ "$project": {
"fields": "$hashmaps.k"
} },
{ "$group": {
"_id": null,
"fields": { "$addToSet": "$fields" }
} },
{ "$project": {
"keys": {
"$setDifference": [
{
"$reduce": {
"input": "$fields",
"initialValue": [],
"in": { "$setUnion" : ["$$value", "$$this"] }
}
},
["_id"]
]
}
}
}
]).toArray()[0]["keys"];
나는 nodejs로 쓰려고 노력했고 마침내 이것을 생각해 냈습니다.
db.collection('collectionName').mapReduce(
function() {
for (var key in this) {
emit(key, null);
}
},
function(key, stuff) {
return null;
}, {
"out": "allFieldNames"
},
function(err, results) {
var fields = db.collection('allFieldNames').distinct('_id');
fields
.then(function(data) {
var finalData = {
"status": "success",
"fields": data
};
res.send(finalData);
delteCollection(db, 'allFieldNames');
})
.catch(function(err) {
res.send(err);
delteCollection(db, 'allFieldNames');
});
});
새로 작성된 콜렉션 "allFieldNames"를 읽은 후 삭제하십시오.
db.collection("allFieldNames").remove({}, function (err,result) {
db.close();
return;
});
mongoldb 문서 에 따라distinct
단일 컬렉션 또는 뷰에서 지정된 필드의 고유 한 값을 찾아 결과를 배열로 반환합니다.
및 인덱스의 수집 작업은 주어진 키 또는 인덱스에 대한 모든 가능한 값을 반환 무엇 :
컬렉션의 기존 인덱스를 식별하고 설명하는 문서 목록이 포함 된 배열을 반환합니다.
그래서 주어진 메소드에서 다음과 같은 메소드를 사용할 수 있습니다. 등록 된 모든 인덱스에 대해 컬렉션을 쿼리하고 키에 대한 인덱스가있는 객체를 반환하십시오 (이 예제는 NodeJS에 대해 async / await를 사용하지만 분명히 다른 비동기 방식을 사용할 수 있습니다).
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 드라이버 고유의 메소드를 사용합니다. 다른 답변이 제안했듯이 집계 프레임 워크와 같은 다른 접근법이 있습니다. 개인적 으로이 방법을보다 유연하게 찾을 수 있습니다. 결과를 반환하는 방법을 쉽게 만들고 미세 조정할 수 있습니다. 분명히 이것은 중첩 속성이 아닌 최상위 속성에만 적용됩니다. 또한 2 차 색인 (기본 _id 이외의 색인)이있는 경우 모든 문서가 표시되도록하려면 해당 색인을로 설정해야합니다 required
.
mongo js 파일을 사용하여이를 달성 할 수 있습니다. getCollectionName.js 파일 에 아래 코드를 추가하고 아래 주어진 Linux 콘솔에서 js 파일을 실행하십시오.
mongo --host 192.168.1.135 getCollectionName.js
db_set = connect("192.168.1.135:27017/database_set_name"); // for Local testing
// db_set.auth("username_of_db", "password_of_db"); // if required
db_set.getMongo().setSlaveOk();
var collectionArray = db_set.getCollectionNames();
collectionArray.forEach(function(collectionName){
if ( collectionName == 'system.indexes' || collectionName == 'system.profile' || collectionName == 'system.users' ) {
return;
}
print("\nCollection Name = "+collectionName);
print("All Fields :\n");
var arrayOfFieldNames = [];
var items = db_set[collectionName].find();
// var items = db_set[collectionName].find().sort({'_id':-1}).limit(100); // if you want fast & scan only last 100 records of each collection
while(items.hasNext()) {
var item = items.next();
for(var index in item) {
arrayOfFieldNames[index] = index;
}
}
for (var index in arrayOfFieldNames) {
print(index);
}
});
quit();
감사합니다 @ackuser
@James Cropcho의 답변에 따라, 나는 사용하기 매우 쉬운 것으로 나타났습니다. 이 도구는 정확히 내가 찾고 있던 mongoeye 입니다.
이 도구를 사용하면 명령 줄에서 스키마를 내보내는 데 약 2 분이 걸렸습니다.
나는이 질문이 10 살이라는 것을 알고 있지만 C # 솔루션이 없으며 이것을 알아내는 데 몇 시간이 걸렸습니다. .NET 드라이버를 사용하고 System.Linq
있으며 키 목록을 반환합니다.
var map = new BsonJavaScript("function() { for (var key in this) { emit(key, null); } }");
var reduce = new BsonJavaScript("function(key, stuff) { return null; }");
var options = new MapReduceOptions<BsonDocument, BsonDocument>();
var result = await collection.MapReduceAsync(map, reduce, options);
var list = result.ToEnumerable().Select(item => item["_id"].ToString());
Carlos LM의 솔루션을 약간 확장하여 더 자세하게 설명했습니다.
스키마의 예 :
var schema = {
_id: 123,
id: 12,
t: 'title',
p: 4.5,
ls: [{
l: 'lemma',
p: {
pp: 8.9
}
},
{
l: 'lemma2',
p: {
pp: 8.3
}
}
]
};
콘솔에 입력하십시오.
var schemafy = function(schema, i, limit) {
var i = (typeof i !== 'undefined') ? i : 1;
var limit = (typeof limit !== 'undefined') ? limit : false;
var type = '';
var array = false;
for (key in schema) {
type = typeof schema[key];
array = (schema[key] instanceof Array) ? true : false;
if (type === 'object') {
print(Array(i).join(' ') + key+' <'+((array) ? 'array' : type)+'>:');
schemafy(schema[key], i+1, array);
} else {
print(Array(i).join(' ') + key+' <'+type+'>');
}
if (limit) {
break;
}
}
}
운영:
schemafy(db.collection.findOne());
산출
_id <number>
id <number>
t <string>
p <number>
ls <object>:
0 <object>:
l <string>
p <object>:
pp <number>
1 간단한 해결 방법이 있습니다 ...
데이터 / 문서를 기본 컬렉션 "things"에 삽입하는 동안 1 개의 개별 컬렉션에 속성을 삽입해야 "things_attributes"라고 할 수 있습니다.
"things"에 삽입 할 때마다 "things_attributes"에서 새 키가있는 경우 해당 문서의 값을 새 문서 키와 비교 한 후 다시 삽입하면 "things_attributes"에서 얻을 수 있습니다.
따라서 things_attributes에는 findOne ()을 사용하여 필요할 때 쉽게 얻을 수있는 고유 키에 대한 하나의 문서 만 있습니다.