2011-12-10 38 views
19

Tôi đang đùa giỡn với Mongo để tạo một dự án thú cưng giống như SO và tôi muốn triển khai các thẻ bài. Mỗi thẻ có một tên và một con sên (chuỗi được sử dụng làm id trong URL) và một bài đăng có nhiều thẻ. Tôi muốn có thể tạo các truy vấn như "tìm các bài đăng có thẻ A, không có thẻ B" và tôi tự hỏi đây là cách nào để làm điều này.Làm cách nào để triển khai thẻ bài trong Mongo?

Một cách là lưu trữ một mảng các id thẻ với mỗi bài đăng - điều này sẽ làm cho truy vấn dễ dàng hơn, nhưng sẽ yêu cầu thêm một bài cho mỗi bài đăng để lấy tên thẻ và sên. Một cách khác là lưu trữ một mảng [tên thẻ, thẻ slug] với mỗi bài đăng, nhưng tôi không chắc chắn tôi có thể sử dụng thông tin đó trong một số find.

Có phương pháp nào khác, phương pháp này sẽ hoạt động tốt hơn cho mongo? Tôi mới đến NoSQL, vì vậy tôi đánh giá cao bất kỳ lời khuyên nào về việc làm thế nào điều này có thể được thực hiện. Ngoài ra, tôi đang sử dụng PHP ràng buộc, nhưng điều đó không nên quan trọng.

Trả lời

38

Nếu các thẻ bạn sử dụng và các sên tương ứng của chúng không thay đổi, tôi nghĩ phương pháp thứ hai của bạn là tốt hơn. Tuy nhiên tôi sẽ đề nghị một sự thay đổi nhỏ - chứ không phải lưu trữ một mảng của [name, slug], làm cho các lĩnh vực rõ ràng bằng cách tạo ra một thẻ subdocument như trong ví dụ này post tài liệu:

{ 
    "_id" : ObjectId("4ee33229d8854784468cda7e"), 
    "title" : "My Post", 
    "content" : "This is a post with some tags", 
    "tags" : [ 
     { 
      "name" : "meta", 
      "slug" : "34589734" 
     }, 
     { 
      "name" : "post", 
      "slug" : "34asd97x" 
     }, 
    ] 
} 

Sau đó bạn có thể truy vấn cho bài viết với một thẻ đặc biệt sử dụng ký hiệu dấu chấm như thế này:

db.test.find({ "tags.name" : "meta"}) 

tags là một mảng, Mongo là đủ thông minh để phù hợp với truy vấn đối với bất kỳ yếu tố của mảng chứ không phải là mảng như một toàn thể, và dot-ký hiệu cho phép bạn để phù hợp với chống lại một trường cụ thể.

Để truy vấn cho bài viết không chứa một từ khóa cụ thể, sử dụng $ne:

db.test.find({ "tags.name" : { $ne : "fish" }}) 

Và để truy vấn cho bài viết có chứa một thẻ nhưng không phải là khác, sử dụng $and:

db.test.find({ $and : [{ "tags.name" : { $ne : "fish"}}, {"tags.name" : "meta"}]}) 

Hope điều này có ích!

+4

là cần thiết để thêm sên vào các thẻ? hoặc có được một mảng giá trị không? –

+2

Tôi nghĩ rằng con sên vừa xảy ra là một chi tiết thực hiện của phương pháp OP. Bạn không cần nó. – Russell

+2

Có truy vấn nào trả về tất cả các thẻ (như nếu bạn muốn tạo một đám mây thẻ)? EDIT: Có vẻ như điều này có thể hoạt động: http://stackoverflow.com/a/4977057/389812 – gdw2

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