Я хотел бы получить имена всех ключей в коллекции MongoDB.
Например, из этого:
db.things.insert( { type : ['dog', 'cat'] } );
db.things.insert( { egg : ['cat'] } );
db.things.insert( { type : [] } );
db.things.insert( { hello : [] } );
Я хочу получить уникальные ключи:
type, egg, hello
Вы можете сделать это с помощью 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"
})
Затем запустите выделение в полученной коллекции, чтобы найти все ключи:
db[mr.result].distinct("_id")
["foo", "bar", "baz", "_id", ...]
С Kristina answer в качестве вдохновения я создал инструмент с открытым исходным кодом под названием Variety, который делает именно это: https://github.com/variety/variety
Попробуйте следующее:
doc=db.thinks.findOne();
for (key in doc) print(key);
Использование 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()
)
Если ваша целевая коллекция не слишком велика, вы можете попробовать это под клиентом оболочки mongo:
var allKeys = {};
db.YOURCOLLECTION.find().forEach(function(doc){Object.keys(doc).forEach(function(key){allKeys[key]=1})});
allKeys;
Вы можете использовать агрегацию с новым $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({$project: {arrayofkeyvalue: {$objectToArray: "$$ROOT"} }}, {$project:{"keys":"$arrayofkeyvalue.k"}})
Вот образец, который работал в Python: Этот образец возвращает результаты inline.
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']
Это отлично работает для меня:
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);
}
Я пытался писать в 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;
});
Я немного расширил решение 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;
}
}
}
Run:
schemafy(db.collection.findOne());
Выход
_id <number>
id <number>
t <string>
p <number>
ls <object>:
0 <object>:
l <string>
p <object>:
pp <number>
У меня есть более простая работа вокруг...
Что вы можете сделать, это вставлять данные/документы в свою основную коллекцию "вещи", которые вы должны вставлять в одну отдельную коллекцию, позволяет сказать "things_attributes".
поэтому каждый раз, когда вы вставляете "вещи", вы получаете от "things_attributes" сравнение значений этого документа с вашими новыми ключами документа, если какой-либо новый ключ присутствует в этом документе и снова вставляет его.
Итак, у вещей-атрибутов будет только один документ уникальных ключей, который вы можете легко получить, когда захотите, используя findOne()
var schematodo = db.[collection].findOne();
for (var key in schematodo) { print (key) ; }