OK, điều này phức tạp hơn một chút vì bạn sẽ cần sử dụng một số đệ quy.
Để thực hiện đệ quy, bạn cần có khả năng lưu trữ một số hàm trên máy chủ.
Bước 1:xác định một số chức năng và đặt chúng ở phía máy chủ
isArray = function (v) {
return v && typeof v === 'object' && typeof v.length === 'number' && !(v.propertyIsEnumerable('length'));
}
m_sub = function(base, value){
for(var key in value) {
emit(base + "." + key, null);
if( isArray(value[key]) || typeof value[key] == 'object'){
m_sub(base + "." + key, value[key]);
}
}
}
db.system.js.save( { _id : "isArray", value : isArray } );
db.system.js.save( { _id : "m_sub", value : m_sub } );
Bước 2:xác định bản đồ và giảm các chức năng
map = function(){
for(var key in this) {
emit(key, null);
if( isArray(this[key]) || typeof this[key] == 'object'){
m_sub(key, this[key]);
}
}
}
reduce = function(key, stuff){ return null; }
Bước 3:chạy bản đồ thu nhỏ và xem kết quả
mr = db.runCommand({"mapreduce" : "things", "map" : map, "reduce" : reduce,"out": "things" + "_keys"});
db[mr.result].distinct("_id");
Kết quả bạn sẽ nhận được là:
["_id", "_id.isObjectId", "_id.str", "_id.tojson", "egg", "egg.0", "foo", "foo.bar", "foo.bar.baaaar", "hello", "type", "type.0", "type.1"]
Có một vấn đề rõ ràng ở đây, chúng tôi đang thêm một số trường không mong muốn ở đây:1. dữ liệu _id2. .0 (trên trứng và loại)
Bước 4:Một số bản sửa lỗi có thể có
Đối với sự cố số 1 việc sửa chữa tương đối dễ dàng. Chỉ cần sửa đổi map
hàm số. Thay đổi điều này:
emit(base + "." + key, null); if( isArray...
về điều này:
if(key != "_id") { emit(base + "." + key, null); if( isArray... }
Sự cố số 2 là một chút xúc xắc hơn. Bạn muốn tất cả các phím và về mặt kỹ thuật "egg.0" is một khóa hợp lệ. Bạn có thể sửa đổi m_sub
để bỏ qua các phím số như vậy. Nhưng cũng có thể dễ dàng nhận thấy một tình huống mà điều này gây phản tác dụng. Giả sử bạn có một mảng liên kết bên trong một mảng thông thường, sau đó bạn muốn "0" đó xuất hiện. Tôi sẽ để phần còn lại của giải pháp đó tùy thuộc vào bạn.