MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

Lọc kết quả theo Giá trị trường mục nhập mảng cuối cùng

Mileage có thể khác nhau về điều này và nó cũng có thể hóa ra rằng "hiện tại" quá trình bạn đang theo dõi hoạt động ít nhất là "phù hợp nhất". Nhưng chúng tôi có thể làm hiệu quả hơn.

Bạn có thể làm gì bây giờ

Với điều kiện các mảng của bạn đã được "sắp xếp" qua sử dụng mã <> $ sort bổ trợ bằng $ push , thì bạn có thể làm được điều này:

db.somedb.find(
  { 
    "partn.is_partner": true,
    "$where": function() {
      return this.partn.slice(-1)[0].is_partner == true;
    }
  },
  { "partn": { "$slice": -1 } }
)

Vì vậy, miễn là partn, is_partner được "lập chỉ mục", điều này vẫn khá hiệu quả vì điều kiện truy vấn ban đầu có thể được đáp ứng bằng chỉ mục. Phần không thể là $ where ở đây sử dụng đánh giá JavaScript.

Nhưng phần thứ hai đó là gì trong $ where đang làm chỉ đơn giản là "cắt" phần tử cuối cùng khỏi mảng và kiểm tra giá trị của is_partner tài sản để xem nếu nó là sự thật. Chỉ khi điều kiện đó cũng được đáp ứng thì tài liệu mới được trả về.

Ngoài ra còn có $ slice toán tử chiếu. Điều này thực hiện tương tự khi trả về phần tử cuối cùng từ mảng. Các kết quả phù hợp sai đã được lọc, vì vậy phần tử này chỉ hiển thị phần tử cuối cùng đúng.

Kết hợp với chỉ mục như đã đề cập, thì điều này sẽ khá nhanh chóng vì các tài liệu đã được chọn sẵn và điều kiện JavaScript chỉ lọc phần còn lại. Lưu ý rằng không có trường khác có điều kiện truy vấn chuẩn để phù hợp, $ where mệnh đề không thể sử dụng một chỉ mục. Vì vậy, hãy luôn cố gắng sử dụng "hạn chế" với các điều kiện truy vấn khác tại chỗ.

Bạn có thể làm gì trong tương lai

Tiếp theo, mặc dù không có sẵn tại thời điểm viết bài, nhưng chắc chắn trong tương lai gần sẽ là $ slice toán tử cho khung tổng hợp. Đây hiện là nhánh của thiết bị đào, nhưng đây là một cái nhìn sơ lược về cách hoạt động của nó:

db.somedb.aggregate([
  { "$match": { "partn.is_partner": true } },
  { "$redact": {
    "$cond": {
      "if": { 
        "$anyElementTrue": {
          "$map": {
            "input": { "$slice": ["$partn",-1] },
            "as": "el",
            "in": "$$el.is_partner"
          }
        }
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }},
  { "$project": {
      "partn": { "$slice": [ "$partn",-1 ] }
  }}
])

Kết hợp $ slice đó trong $ redact ở đây thông báo cho các tài liệu được lọc với một điều kiện logic, kiểm tra tài liệu. Trong trường hợp này, $ slice tạo ra một mảng phần tử duy nhất được gửi tới $ bản đồ để chỉ trích xuất một is_partner giá trị (vẫn là một mảng). Vì đây vẫn là một mảng phần tử đơn lẻ, nên thử nghiệm còn lại là $ anyElementTrue điều này làm cho kết quả này là một kết quả boolean số ít, phù hợp với $ cond .

$ redact ở đây quyết định kết quả đó có nên $$ KEEP hay không hoặc $$ PRUNE tài liệu từ các kết quả. Sau đó, chúng tôi sử dụng $ slice lại trong dự án để chỉ trả về phần tử cuối cùng của mảng sau khi lọc.

Điều đó hoạt động khá chính xác so với những gì phiên bản JavaScript làm, ngoại trừ việc phiên bản này sử dụng tất cả các toán tử được mã hóa gốc và do đó sẽ nhanh hơn một chút so với phiên bản JavaScript thay thế.

Cả hai biểu mẫu đều trả về tài liệu đầu tiên của bạn như mong đợi:

{
    "_id" : 0,
    "partn" : [
            {
                    "date" : ISODate("2015-07-28T00:59:14.963Z"),
                    "is_partner" : true
            },
            {
                    "date" : ISODate("2015-07-28T01:00:32.771Z"),
                    "is_partner" : false
            },
            {
                    "date" : ISODate("2015-07-28T01:15:29.916Z"),
                    "is_partner" : true
            },
            {
                    "date" : ISODate("2015-08-05T13:48:07.035Z"),
                    "is_partner" : false
            },
            {
                    "date" : ISODate("2015-08-05T13:50:56.482Z"),
                    "is_partner" : true
            }
    ]
}

Lợi ích lớn ở đây với cả hai là mảng của bạn phải được sắp xếp nên ngày mới nhất là ngày đầu tiên. Nếu không có điều đó, thì bạn cần khung tổng hợp để $ sort mảng, giống như bạn đang làm bây giờ.

Không thực sự hiệu quả, vì vậy đó là lý do tại sao bạn nên "sắp xếp trước" mảng của mình và duy trì thứ tự trên mỗi lần cập nhật.

Là một thủ thuật hữu ích, điều này thực sự sẽ sắp xếp lại thứ tự tất cả các phần tử mảng trong tất cả các tài liệu bộ sưu tập trong một câu lệnh đơn giản:

db.somedb.update(
    {},
    { "$push": { 
        "partn": { "$each": [], "$sort": { "date": 1 } }
    }},
    { "multi": true }
)

Vì vậy, ngay cả khi bạn không "đẩy" một phần tử mới vào một mảng và chỉ cập nhật một thuộc tính, bạn luôn có thể áp dụng cấu trúc cơ bản đó để giữ cho mảng được sắp xếp theo cách bạn muốn.

Đáng xem xét vì nó sẽ giúp mọi thứ nhanh hơn nhiều.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Mongo Connection Pooling (Thay đổi kích thước của nhóm kết nối)

  2. Cách tốt nhất để lập mô hình hệ thống bỏ phiếu trong MongoDB

  3. MongoDB không được ủy quyền cho truy vấn - mã 13

  4. Khoảng cách in MongoDB giữa hai điểm

  5. 5 cách để có được một giờ cho một buổi hẹn hò trong MongoDB