2010-07-29 31 views
5

Tôi vừa hoàn thành cuốn sách "couchdb: hướng dẫn dứt khoát" và bắt đầu chơi với các tài liệu thiết kế. tuy nhiên có một điều mà tôi không hiểu. Tất cả các ví dụ tôi đã thấy cho đến nay là hơi tuyến tính.Làm cách nào tôi có thể gọi một chế độ xem khác trong chế độ xem couchdb?

Ví dụ:

{ 
    "_id": "1", 
    "_rev": ".....", 
    "name": "first", 
    "something": "blue", 
    "child": "2" 
} 

{ 
    "_id": "2", 
    "_rev": ".....", 
    "name": "second", 
    "something": "green", 
    "child": "3" 
    "parent" : "1" 
    } 

{ 
    "_id": "3", 
    "_rev": ".....", 
    "name": "second", 
    "something": "red", 
    "parent" : "2"; 
} 

Tôi không có vấn đề viết một cái nhìn, mà trả về tất cả các màu: (!)

function(doc) { 
     if (doc.something) { 
      emit(doc.something,doc._id);  
    } 
} 

Nhưng nếu tôi muốn biết tất cả con cháu (không trẻ em, xin lỗi lỗi của tôi) cho phần tử với _id = 1 ("something": "blue")? Kinh nghiệm lập trình của tôi nói với tôi, rằng tôi nên sử dụng đệ quy, nhưng tôi không biết làm thế nào. Làm thế nào tôi có thể gọi một chức năng xem, từ một chức năng xem?

Nói chung: vấn đề này phát sinh, khi bạn thiết kế cơ sở dữ liệu có tham chiếu giữa các tài liệu json. Cụ thể hơn với mối quan hệ chuyển tiếp giữa các phần tử.

Edit: Ví dụ: Tôi chỉ biết _id = 1 và kết quả nên được một cái gì đó như [_id = 2, _id = 3], bởi vì 2 là một đứa trẻ trong tổng số 1 và 3 là con của 2.

Trả lời

8

Nếu có thể, không xác định thứ bậc tài liệu theo cách này - bạn sẽ chiến đấu với CouchDB từng bước của con đường.

Bạn thực sự không thể thực hiện phân cấp đi bộ trong chế độ xem. Chế độ xem có nghĩa là để chuyển từng tài liệu một cách độc lập trên các bản đồ khác (bản đồ) và tạo ra một số giá trị tổng hợp từ chúng (giảm).

Bạn có thể sử dụng danh sách để hoạt động trên nhiều tài liệu cùng một lúc, nhưng đó cũng không phải là giải pháp tốt.

Nếu bạn cần phải giữ cho cấu trúc dữ liệu này (liên kết đến các phụ huynh/trẻ em), tôi đề nghị bạn nhận được lắp ráp cấu trúc từ bên ngoài CouchDB: có được tài liệu gốc, có con của nó, có con của họ, vv

Tuy nhiên, cách ưa thích của lưu trữ một cây trong CouchDB là phải có mỗi nút nhớ đó là con đường trong cây:

{ 
    "_id": "1", 
    "name": "first", 
    "something": "blue", 
    "path": [1] 
} 

{ 
    "_id": "2", 
    "name": "second", 
    "something": "green", 
    "path": [1,2] 
    } 

{ 
    "_id": "3", 
    "name": "second", 
    "something": "red", 
    "path": [1,2,3] 
} 

sau đó bạn có thể sử dụng điểm này để có được hậu duệ của một tài liệu:

function(doc) { 
    for (var i in doc.path) { 
     emit([doc.path[i], doc.path], doc) 
    } 
} 

Để có được hậu duệ của _id 1 bạn có thể chạy truy vấn này:

http://c.com/db/_design/colors/_view/descendants?startkey=[1]&endkey=[1,{}] 

Lưu trữ một đường dẫn đầy đủ đã nhược điểm riêng của nó, cũng vậy, mặc dù. Tôi đề nghị bạn kiểm tra điều này CouchDB wiki page on trees. Nguồn cho điều đó là this blog post by Paul Bonser.

+0

Tôi cần mô hình hóa mối quan hệ giữa các phần tử, như được mô tả. Tuy nhiên tôi có sự sang trọng để di chuyển logic trong một ứng dụng web java, đó là phần nào là một wrapper cho ứng dụng couchdb. Ý định của tôi là di chuyển càng nhiều logic càng tốt vào tài liệu thiết kế couchdb và tránh nhiều cuộc gọi. Tôi sẽ thử cả hai cách tiếp cận mà bạn đã đề cập: a) nhiều cuộc gọi đến ("lấy tài liệu gốc, nhận con, đưa con cái, v.v.") và b) lưu đường dẫn đầy đủ (ít mong muốn hơn) và xem nhanh hơn/tốt hơn. Cảm ơn bạn đã trả lời. –

+0

Cảm ơn câu hỏi. Tôi đã học được những thứ mới trong khi trả lời nó. Nó sẽ là tuyệt vời nếu bạn đăng những phát hiện của bạn ở đây (hoặc bất cứ nơi nào trên web) khi bạn tìm ra những gì làm việc tốt nhất cho bạn. –

1

trong ví dụ bạn có ở trên, để có được tất cả các trẻ em cho một ID tài liệu, chức năng bản đồ của bạn sẽ trông như thế này:

function (doc) { 
    if (doc.parent) { 
     emit(doc.parent, { "_id": doc._id }); 
    } 
} 

(các "con" tài sản mà bạn có trong tài liệu 2 thậm chí không cần thiết.)

Với dữ liệu ví dụ của bạn, điều này sẽ phát ra hai lần:

[ "1", { "_id": "2" } ] 
[ "2", { "_id": "3" } ] 

Để có được ID đứa trẻ cho một người mẹ độc thân, bạn sẽ truy cập vào xem như sau:

http://.../db/_design/viewName/_view/childfunc?key="2" 

Để có được tài liệu đầy đủ , thêm tham số include_docs vào chuỗi truy vấn.

Nếu bạn muốn nhận được các phụ huynh và trẻ cùng một lúc, chức năng bản đồ của bạn chỉ là một chút khác nhau:

function (doc) { 
    emit([ doc._id, "" ], { "_id": doc.id }); 
    if (doc.parent) { 
     emit([ doc.parent, doc._id ], { "_id": doc.id }) 
    } 
} 

Chức năng này có thể phát ra hai lần, vì vậy bạn kết thúc với những điều sau đây:

[ [ "1", "" ], { "_id": "1" } ] 
[ [ "1", "2" ], { "_id": "2" } ] 
[ [ "2", "" ], { "_id": "2" } ] 
[ [ "2", "3" ], { "_id": "3" } ] 
[ [ "3", "" ], { "_id": "3" } ] 

Nhờ sắp xếp sắp xếp, cha mẹ sẽ kết thúc trước (vì phần tử khóa thứ hai của chúng là "") và các con sẽ kết thúc sau đó. Bạn không phải sử dụng child _id làm phần tử khóa thứ hai, bạn có thể sử dụng bất kỳ thuộc tính phân loại tự nhiên nào có ý nghĩa nhất. (. Sáng tạo Cập nhật, tên, chức danh, bất cứ điều gì)

Nếu bạn không có "con" thuộc tính, bạn có thể làm cho một giảm chức năng để có được tất cả các trẻ em của cha mẹ:

function (key, vals) { 
    var children = []; 
    for (var docId in vals) { 
     if (key[1] !== "") { 
      children.push(docId); 
     } 
    } 
    return children; 
} 

Đó là chức năng xem xét xem phần con của khóa có trống không, và nếu như vậy nó sẽ đẩy ID tài liệu vào một mảng.Nó lặp lại tất cả các giá trị theo cách này và trả về mảng khi hoàn thành.

+1

Tôi đã phạm sai lầm. Tôi không có ý là trẻ em. Tôi có nghĩa là con cháu. Lấy làm tiếc. Giải pháp của bạn hoạt động với vấn đề trẻ em. Nhưng nếu tôi cần truy cập một chức năng bản đồ khác từ bên trong hàm reduce. Ví dụ để kiểm tra các phím chống lại một số tiêu chí khác? Không thể gọi chức năng bản đồ từ bên trong chức năng giảm hoặc bản đồ? Ví dụ nếu tôi cần phải so sánh hai hoặc nhiều tài liệu với nhau? Trong một hàm tôi chỉ xem xét một tài liệu tại một thời điểm, nhưng tôi không thể so sánh hai tài liệu khác nhau mà không lưu các giá trị ở đâu đó. –

Các vấn đề liên quan