2015-07-03 14 views
7

Tôi đã nhập một số loại dữ liệu XML cẩu thả vào cơ sở dữ liệu Mongo. Mỗi Tài liệu có các tài liệu phụ lồng nhau đến độ sâu khoảng 5-10. Tôi muốn tìm() tài liệu có giá trị cụ thể của một trường cụ thể, trong đó trường có thể xuất hiện ở bất kỳ độ sâu nào trong các tài liệu phụ (và có thể xuất hiện nhiều lần).Cách tìm tên trường MongoDB ở độ sâu tùy ý

Tôi hiện đang kéo từng tài liệu vào Python và sau đó tìm kiếm từ điển đó, nhưng sẽ tốt hơn nếu tôi có thể nêu mẫu thử nghiệm nơi cơ sở dữ liệu chỉ trả về tài liệu có giá trị cụ thể của tên trường ở đâu đó trong nội dung của chúng .

Dưới đây là một tài liệu ví dụ:

{ 
    "foo": 1, 
    "bar": 2, 
    "find-this": "Yes!", 
    "stuff": { 
     "baz": 3, 
     "gobble": [ 
      "wibble", 
      "wobble", 
      { 
       "all-fall-down": 4, 
       "find-this": "please find me" 
      }     
     ], 
     "plugh": { 
      "plove": { 
       "find-this": "Here too!" 
      } 
     } 
    } 
} 

Vì vậy, tôi muốn tìm các tài liệu có một "tìm-này" lĩnh vực, và (nếu có thể) để có thể tìm các tài liệu có một giá trị cụ thể của trường "tìm này".

+0

Thánh server-side scripting, Batman! Tôi không biết bạn có thể chạy JS trong cơ sở dữ liệu! Đó là thực sự mát mẻ, và giải pháp của bạn làm cho cảm giác hoàn hảo. Cảm ơn rất nhiều! –

+0

Ồ, bạn biết không?Tôi đặt cược bạn có thể thực hiện tìm kiếm() với mệnh đề "hoặc" $ where: để cơ sở dữ liệu tìm "khóa-tìm-kiếm" và "giá trị để tìm kiếm" bằng cách sử dụng cơ chế (nhanh) của chính nó cho nơi khóa cấp cao nhất, và cung cấp chức năng JS đệ quy tìm kiếm được sử dụng trên tất cả các nút mà "key-to-search" không ở cấp cao nhất. Tôi sẽ thêm nó vào câu hỏi này nếu tôi có thể làm cho nó hoạt động. –

Trả lời

7

Bạn đúng trong tuyên bố nhất định về tài liệu BSON không phải là tài liệu XML. Vì XML được nạp vào một cấu trúc cây bao gồm "các nút", việc tìm kiếm trên một khóa đơn giản là khá dễ dàng.

Một tài liệu MonoDB không quá đơn giản để xử lý và đây là "cơ sở dữ liệu" ở nhiều khía cạnh, do đó, nó thường được mong đợi có một "đồng nhất" nhất định của vị trí dữ liệu để dễ dàng cho cả hai "chỉ mục "và tìm kiếm.

Tuy nhiên, nó có thể được thực hiện. Nhưng tất nhiên điều này có nghĩa là một quá trình đệ quy thực hiện trên máy chủ và điều này có nghĩa là xử lý JavaScript với $where.

Như một ví dụ vỏ cơ bản, nhưng nói chung function chỉ là một cuộc tranh luận chuỗi các $where hành khắp mọi nơi khác:

db.collection.find(
    function() { 
    var findKey = "find-this", 
     findVal = "please find me"; 

    function inspectObj(doc) { 
     return Object.keys(doc).some(function(key) { 
     if (typeof(doc[key]) == "object") { 
      return inspectObj(doc[key]); 
     } else { 
      return (key == findKey && doc[key] == findVal); 
     } 
     }); 
    } 
    return inspectObj(this); 
    } 
) 

Vì vậy, về cơ bản, kiểm tra các phím hiện trong đối tượng để xem họ có phù hợp với mong muốn "tên trường" và nội dung. Nếu một trong các khóa đó xảy ra là một "đối tượng", sau đó recurse vào chức năng và kiểm tra lại.

JavaScript .some() đảm bảo rằng kết quả "đầu tiên" được tìm thấy sẽ trả về từ hàm tìm kiếm cho kết quả true và trả về đối tượng mà "khóa/giá trị" đó có mặt ở một số độ sâu.

Lưu ý rằng $where về cơ bản có nghĩa là duyệt toàn bộ bộ sưu tập của bạn trừ khi có một số bộ lọc truy vấn hợp lệ khác có thể được áp dụng cho "chỉ mục" trên bộ sưu tập.

Vì vậy, hãy sử dụng cẩn thận hoặc hoàn toàn không làm việc với việc tái cấu trúc dữ liệu thành một biểu mẫu khả thi hơn.

Nhưng điều này sẽ cho bạn kết quả phù hợp.

2

Dưới đây là một ví dụ, mà tôi sử dụng để tìm kiếm đệ quy cho Key-Value bất cứ nơi nào trong cấu trúc tài liệu:

db.getCollection('myCollection').find({ 

    "$where" : function(){ 

     var searchKey = 'find-this'; 
     var searchValue = 'please find me'; 

     return searchInObj(obj); 

     function searchInObj(obj){        
      for(var k in obj){  
      if(typeof obj[k] == 'object' && obj[k] !== null){ 
       if(searchInObj(obj[k])){ 
       return true; 
       } 
      } else { 
       if(k == searchKey && obj[k] == searchValue){ 
       return true; 
       } 
      }   
      }       
      return false; 
     }  
    }  
}) 
Các vấn đề liên quan