Giới Thiệu
Bài viết gốc được xuất bản ngày 18 tháng 1 năm 2019 tại ObjectRocket.com/blog.
Để validate schema, debug typo trong trường, hoặc tìm trường bạn không nên thiết lập, bạn cần hiểu tất cả key trong collection MongoDB® của mình.
Nhiều công ty MongoDB-as-a-Service, bao gồm ObjectRocket, cung cấp cách dễ dàng làm điều này ngay trong giao diện người dùng (UI). Người dùng MongoDB dày dạn kinh nghiệm thường bắt đầu với object-document mapper (ODM), như Mongoose cho JavaScript® hoặc Mongoengine cho Python®, để xây dựng schema nhất quán cho ứng dụng và giảm typo. ODM cũng làm type validation, nên bạn không vô tình đặt string vào trường có integer và áp dụng toán học.
Nếu bạn không có service hoặc ODM, bạn có thể dùng một số phương pháp khác để truy cập key. Chúng tôi tìm thấy các phương pháp sau để lấy tất cả key trong collection MongoDB cho các hoàn cảnh khác nhau.
Tìm Key MongoDB
Giả sử bạn có ví dụ sau:
db.activities.insert( { type : ['indoor', 'outdoor' , 'mixed'] } );
db.activities.insert( { activity : 'cycling' } );
db.activities.insert( { activity : 'skiing', location: 'Alpes', } );
db.activities.insert( { equipment : ['paddles','sunglasses'] } );
Bạn cần lấy các key duy nhất: type, activity, equipment, và location.
MapReduce
Bạn có thể lấy key với MapReduce bằng thao tác sau:
mr = db.runCommand({
"mapreduce" : "activities",
"map" : function() {
for (var key in this) {
emit(key, null);
}
},
"reduce" : function(key, stuff) {
return null;
},
"out": "activities" + "_keys"
})
Sau khi thao tác kết thúc, chạy lệnh distinct sau trên collection kết quả để tìm tất cả key:
db.activities_keys.distinct("_id")
Nếu bạn muốn lấy danh sách tất cả key duy nhất trong subdocument, sửa dòng sau:
for (var key in this.first_level.second_level.nth_level) { emit(key, null); }
Aggregation
Bạn cũng có thể dùng aggregation. Phương pháp này hoạt động với tất cả driver hỗ trợ aggregate framework. Với aggregations của bạn, dùng $sample hoặc $limit để giảm overhead.
Lưu ý: Chạy với primary read preference có thể ảnh hưởng hiệu suất. Cân nhắc chạy với secondary read preference.
Dùng aggregation với $objectToArrray (có sẵn phiên bản 3.4.4 trở lên) để chuyển đổi tất cả cặp key-value cấp cao nhất thành mảng document, tiếp theo $unwind và $group với $addToSet để lấy key distinct trên toàn collection.
Trong ví dụ sau, $$ROOT tham chiếu document cấp cao nhất.
db.activities.aggregate([
{"$project":{"arrayofkeyvalue":{"$objectToArray":"$$ROOT"}}},
{"$unwind":"$arrayofkeyvalue"},
{"$group":{"_id":null,"allkeys":{"$addToSet":"$arrayofkeyvalue.k"}}}
])
Bạn cũng có thể dùng aggregation để lấy key trong một document đơn lẻ bằng lệnh sau:
db.activities.aggregate([
{"$project":{"arrayofkeyvalue":{"$objectToArray":"$$ROOT"}}},
{"$project":{"keys":"$arrayofkeyvalue.k"}}
])
Mongo Shell
Bạn cũng có thể lấy key dưới Mongo shell client bằng lệnh sau:
var allKeys = {};
db.YOURCOLLECTION.find().forEach(function(doc){
Object.keys(doc).forEach(function(key){
allKeys[key]=1
})
});
allKeys;
Output Trường Cho Một Document Đơn Lẻ
Vì mỗi document trong collection có thể có key hoàn toàn khác nhau, bạn có thể cần output trường cho một document đơn lẻ trong collection. Dùng lệnh sau để làm điều này:
doc=db.thinks.findOne();
for (key in doc) print(key);
Python
Bạn có thể dùng Python để lấy MongoDB key. Ví dụ sau trả về set của tất cả key cấp cao nhất trong collection:
#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() )
JavaScript
JavaScript cung cấp cách khác để lấy key, như ví dụ sau:
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');
});
}
);
Sau khi đọc collection mới tạo allFieldNames, xóa nó.
db.collection("allFieldNames").remove({}, function (err,result) {
db.close();
return;
});
Nhiều Lựa Chọn
Bạn có rất nhiều tùy chọn để lấy Mongo key này. Nếu bạn bị ngợp bởi quản trị MongoDB và muốn tập trung vào code thay vì quản trị database, chúng tôi ở đây cho bạn.