2011-07-17 35 views

Trả lời

15

Bây giờ MongoDB (2,6 phát hành) supports$size hoạt động trong tập hợp.

Từ các tài liệu:

{ <field>: { $size: <array> } } 

gì bạn muốn có thể được thực hiện như sau với một trong hai bằng cách sử dụng này:

db.users.aggregate(
    [ 
     { 
     $group: { 
      _id: "$username", 
      tags_count: {$first: {$size: "$tags" }} 
     } 
     } 
    ] 
) 

hoặc

db.users.aggregate(
    [ 
     { 
     $project: { 
      tags_count: {$size: "$tags"} 
     } 
     } 
    ] 
) 
+6

Tôi không nghĩ bạn có thể sử dụng toán tử kích thước $ như thế này với $ group. Kích thước $ không nằm trong số [toán tử tập hợp] (http://docs.mongodb.org/manual/reference/operator/aggregation-group/). Thay vào đó, bạn có thể sử dụng chiếu nếu bạn không cần nhóm: db.test.aggregate ({$ dự án: đếm: {$ Kích thước: "$ tags"}}) HOẶC nếu bạn không cần nhóm , smth như thế này: db.test.aggregate ({$ group: {_id: "$ userName", đếm: {$ sum: {$ size: "$ tags"}}}}) –

+0

thú vị mà không ai phàn nàn về nó trước, nhờ – anvarik

+0

Làm thế nào để có thể nhận được khi tôi có một cái gì đó như thế này: {tên người dùng: 'Alex', thẻ: [['C#', 'Java', 'C++']]} Làm thế nào chúng ta có thể nhận được chiều dài/kích thước của thẻ bây giờ? – rkatkam

9

Hiện tại, cách duy nhất để thực hiện việc này dường như đang sử dụng db.eval, nhưng điều này là locks database for other operations.

Cách hiệu quả nhất về tốc độ sẽ thêm trường bổ sung lưu trữ độ dài của mảng và duy trì nó theo các hoạt động $inc$push.

+0

Cảm ơn bạn rất nhiều.Đúng, tôi cũng nghĩ về việc giữ kích thước trong một lĩnh vực riêng biệt, nhưng hy vọng rằng sẽ có một cách tốt hơn. –

15

Tôi nghĩ rằng có thể hiệu quả hơn để tính số lượng thẻ trên mỗi lần lưu (dưới dạng một trường riêng biệt) bằng cách sử dụng $inc có lẽ hoặc thông qua công việc theo lịch biểu.

Bạn cũng có thể thực hiện việc này với bản đồ/giảm (số canonical example) nhưng điều đó dường như không phải là điều bạn muốn.

Tôi không chắc nó có thể thực hiện chính xác những gì bạn đang yêu cầu, nhưng bạn có thể truy vấn tất cả các tài liệu phù hợp với một kích thước nhất định với $size ...

> db.collection.find({ tags : { $size: 3 }}); 

Đó sẽ giúp bạn có được tất cả các tài liệu với 3 thẻ ...

+0

Cảm ơn bạn đã cho lời khuyên kích thước $, Justin. –

29

nếu tên người dùng Alex là duy nhất, bạn có thể sử dụng mã tiếp theo: câu trả lời

db.test.insert({username:"Alex", tags: ['C#', 'Java', 'C++'] }); 
db.test.aggregate(
    {$match: {username : "Alex"}}, 
    {$unwind: "$tags"}, 
    {$project: {count:{$add:1}}}, 
    {$group: {_id: null, number: {$sum: "$count" }}} 
); 
{ "result" : [ { "_id" : null, "number" : 3 } ], "ok" : 1 } 
+1

Cảm ơn bạn. Câu hỏi đã được hỏi lại khi khung tổng hợp không có sẵn, nhưng bây giờ nó có ý nghĩa hoàn hảo. –

10

xmm.dev có thể được đơn giản hóa: thay vì phải đồng interm trường' UNT', bạn có thể tổng hợp trực tiếp trong $ nhóm:

db.test.aggregate(
    {$match: {username : "Alex"}}, 
    {$unwind: "$tags"}, 
    {$group: {_id: null, number: {$sum: 1 }}} 
) 
0

Tôi đã làm một công việc nhỏ xung quanh khi tôi cần truy vấn kích thước mảng và trả về nếu nó lớn hơn 0 nhưng có thể là bất cứ thứ gì từ 1-3.

Đây là giải pháp của tôi:

db.test.find($or : [{$field : { $exists : true, $size : 1}}, 
        {$field : { $exists : true, $size : 2}}, 
        {$field : { $exists : true, $size : 3}}, ]) 

này về cơ bản trả về một tài liệu khi thuộc tính tồn tại và kích thước là 1, 2, hoặc 3. Người sử dụng có thể thêm nhiều câu lệnh và tăng nếu họ đang tìm kiếm một kích thước cụ thể hoặc trong phạm vi. Tôi biết nó không hoàn hảo nhưng nó đã hoạt động và tương đối nhanh. Tôi chỉ có 1-3 kích thước trong thuộc tính của tôi để giải pháp này hoạt động.

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