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

Cách sử dụng $ regex bên trong $ hoặc dưới dạng Biểu thức tổng hợp

Mọi thứ bên trong $ expr là một biểu thức tổng hợp và tài liệu có thể không "nói rằng bạn không thể rõ ràng" , nhưng thiếu bất kỳ toán tử được đặt tên nào sự cố JIRA SERVER-11947 chắc chắn nói rằng. Vì vậy, nếu bạn cần một biểu thức chính quy thì bạn thực sự không có lựa chọn nào khác ngoài việc sử dụng $ where thay vào đó:

db.getCollection('permits').find({
  "$where": function() {
    var description = this.inspections
       .sort((a,b) => b.inspectionDate.valueOf() - a.inspectionDate.valueOf())
       .shift().description;

     return /^Found a .* at the property$/.test(description) ||
           description === "Health Inspection";

  }
})

Bạn vẫn có thể sử dụng $ expr và biểu thức tổng hợp cho một kết hợp chính xác hoặc chỉ giữ so sánh trong $ ở đâu dù sao. Nhưng tại thời điểm này, cụm từ thông dụng duy nhất mà MongoDB hiểu là $ regex trong biểu thức "truy vấn" .

Nếu bạn thực sự đã "yêu cầu" biểu thức đường ống tổng hợp ngăn bạn sử dụng $ where , thì cách tiếp cận hợp lệ duy nhất hiện tại là đầu tiên "chiếu" trường riêng biệt với mảng và sau đó $ match với biểu thức truy vấn thông thường:

db.getCollection('permits').aggregate([
  { "$addFields": {
     "lastDescription": {
       "$arrayElemAt": [
         "$inspections.description",
         { "$indexOfArray": [
           "$inspections.inspectionDate",
           { "$max": "$inspections.inspectionDate" }
         ]}
       ]
     }
  }},
  { "$match": {
    "lastDescription": {
      "$in": [/^Found a .* at the property$/,/Health Inspection/]
    }
  }}
])

Điều này dẫn chúng ta đến thực tế là bạn dường như đang tìm kiếm mục trong mảng có giá trị ngày lớn nhất. Cú pháp JavaScript phải làm rõ rằng cách tiếp cận chính xác ở đây là thay vì $ sort mảng trên "cập nhật". Theo cách đó, mục "đầu tiên" trong mảng có thể là "mới nhất". Và đây là điều bạn có thể làm với một truy vấn thông thường.

Để duy trì đơn đặt hàng, hãy đảm bảo các mục mới được thêm vào mảng có $ push $ sort như thế này:

db.getCollection('permits').updateOne(
  { "_id": _idOfDocument },
  {
    "$push": {
      "inspections": {
        "$each": [{ /* Detail of inspection object */ }],
        "$sort": { "inspectionDate": -1 }
      }
    }
  }
)

Trên thực tế, với một đối số mảng trống cho $ each một updateMany () sẽ cập nhật tất cả các tài liệu hiện có của bạn:

db.getCollection('permits').updateMany(
  { },
  {
    "$push": {
      "inspections": {
        "$each": [],
        "$sort": { "inspectionDate": -1 }
      }
    }
  }
)

Chúng chỉ thực sự cần thiết khi bạn thực sự "thay đổi" ngày được lưu trữ trong quá trình cập nhật và những bản cập nhật đó tốt nhất nên được phát hành bằng BulkWrite () để thực hiện hiệu quả "cả" việc cập nhật và "sắp xếp" mảng:

db.getCollection('permits').bulkWrite([
  { "updateOne": {
    "filter": { "_id": _idOfDocument, "inspections._id": indentifierForArrayElement },
    "update": {
      "$set": { "inspections.$.inspectionDate": new Date() }
    }
  }},
  { "updateOne": {
    "filter": { "_id": _idOfDocument },
    "update": {
      "$push": { "inspections": { "$each": [], "$sort": { "inspectionDate": -1 } } }
    }
  }}
])

Tuy nhiên, nếu bạn chưa từng thực sự "thay đổi" ngày, thì có lẽ sẽ hợp lý hơn nếu bạn chỉ cần sử dụng $ position sửa đổi và "xếp trước" vào mảng thay vì "thêm" và tránh bất kỳ chi phí nào của $ sort :

db.getCollection('permits').updateOne(
  { "_id": _idOfDocument },
  { 
    "$push": { 
      "inspections": {
        "$each": [{ /* Detail of inspection object */ }],
        "$position": 0
      }
    }
  }
)

Với mảng được sắp xếp vĩnh viễn hoặc ít nhất được xây dựng để ngày "mới nhất" thực sự luôn là mục nhập "đầu tiên", khi đó bạn có thể chỉ cần sử dụng biểu thức truy vấn thông thường:

db.getCollection('permits').find({
  "inspections.0.description": { 
    "$in": [/^Found a .* at the property$/,/Health Inspection/]
  }
})

Vì vậy, bài học ở đây là đừng thử và ép các biểu thức được tính toán dựa trên logic của bạn, nơi bạn thực sự không cần. Không có lý do thuyết phục nào khiến bạn không thể sắp xếp nội dung mảng là "được lưu trữ" để có "ngày mới nhất đầu tiên " và ngay cả khi bạn nghĩ rằng bạn cần mảng theo bất kỳ thứ tự nào khác thì có lẽ bạn nên cân nhắc xem trường hợp sử dụng nào quan trọng hơn.

Sau khi được tạo lại, bạn thậm chí có thể tận dụng lợi thế của một chỉ mục ở một mức độ nào đó miễn là các biểu thức chính quy được neo vào đầu chuỗi hoặc ít nhất một cái gì đó khác trong biểu thức truy vấn khớp chính xác.

Trong trường hợp bạn cảm thấy mình thực sự không thể sắp xếp lại mảng, thì mã <> $ ở đâu truy vấn là tùy chọn hiện tại duy nhất của bạn cho đến khi vấn đề JIRA được giải quyết. Đây thực sự là hy vọng dành cho bản phát hành 4.1 như được nhắm mục tiêu hiện tại, nhưng nhiều khả năng là ước tính tốt nhất là 6 tháng đến một năm.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Chúng ta có thể sử dụng kho dữ liệu mùa xuân để cập nhật các tài liệu nhúng trong mongodb không

  2. Đường dẫn tra cứu:mảng địa phương `$ match`` $ in` khi từ giá trị là mảng và giá trị cục bộ được tìm thấy

  3. DB-ref trong mongoose mà không có Schema.ObjectId?

  4. Biểu thức không được công nhận '$ đầu tiên'

  5. Truy vấn một trường con trong documentdb