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

$ expr arrayElementAt không hoạt động khi tổng hợp tài liệu được nhúng

Sửa nhanh

"Đường ống dẫn" của bạn không hoạt động ở đây chủ yếu $ project ban đầu của bạn thiếu trường bạn muốn sử dụng giai đoạn sau. "sửa chữa nhanh" do đó về cơ bản là bao gồm trường đó trong tài liệu "dự kiến", vì đó là cách các giai đoạn của đường ống tổng hợp hoạt động:

array(
  array(
    '$project' => array(
      'FullName' => array('$concat' => array('$first_name', ' ', '$middle_name', ' ', '$last_name')),
      'FirstMiddle' => array('$concat' => array('$first_name', ' ', '$middle_name')),
      'FirstLast' => array('$concat' => array('$first_name', ' ', '$last_name')),
      'FirstName' => array('$concat' => array('$first_name')),
      'MiddleName' => array('$concat' => array('$middle_name')),
      'LastName' => array('$concat' => array('$last_name')),
      'Student' => '$$ROOT',
      'allotment_details' => 1 # that's the change
    )
  ),

Hoặc thậm chí kể từ khi bạn sử dụng $$ ROOT dành cho Student dù sao, chỉ cần đủ điều kiện cho trường theo đường dẫn đó:

'$expr' => array(
  '$eq'=> array(
    array('$arrayElemAt' => array('$Student.allotment_details.room_id', -1)),
    $this->RoomId
  )
),

tuy nhiên Tôi sẽ mạnh mẽ * cầu xin rằng bạn KHÔNG PHẢI làm điều đó.

Toàn bộ khái niệm về "nối chuỗi" để thực hiện $ match về nội dung là một ý tưởng thực sự tồi vì nó có nghĩa là toàn bộ bộ sưu tập được viết lại trong đường dẫn trước khi bất kỳ "quá trình lọc" nào thực sự được thực hiện.

Tương tự như vậy, tìm kiếm để khớp trên phần tử mảng "cuối cùng" cũng là một vấn đề. Một cách tiếp cận tốt hơn nhiều là thay vào đó thực sự thêm "mục mới" vào "đầu" của mảng, thay vì "kết thúc". Đây thực sự là những gì $ position hoặc thậm chí có thể là $ sort sửa đổi thành $ push làm cho bạn, bằng cách thay đổi nơi các mục được thêm vào hoặc thứ tự sắp xếp của các mục tương ứng.

Thay đổi Mảng thành "mới nhất đầu tiên"

Điều này sẽ mất một chút công việc bằng cách thay đổi cách bạn lưu trữ mọi thứ, nhưng lợi ích là tốc độ của các truy vấn như bạn muốn được cải thiện đáng kể mà không cần $ expr được đánh giá đối số.

Các khái niệm cốt lõi là "sắp xếp trước" các mục mảng mới với cú pháp như:

$this->collection->updateOne(
  $query,
  [ '$push' => [ 'allotment_details' => [ '$each' => $allotments, '$position' => 0 ] ] ]
)

Trong đó $ alloments phải là một mảng theo yêu cầu của $ each $ position được sử dụng để 0 để thêm mục mảng mới "đầu tiên".

Thay vào đó, nếu bạn thực sự có một cái gì đó như created_date dưới dạng thuộc tính bên trong mỗi đối tượng trong mảng, thì bạn "có thể" sử dụng một cái gì đó như $ sort thay vào đó như một bổ ngữ.

$this->collection->updateOne(
  $query,
  [ '$push' => [
      'allotment_details' => [ '$each' => $allotments, '$sort' => [ 'created_date' => -1 ] ]
  ]]
)

Nó thực sự phụ thuộc vào việc "truy vấn" và các yêu cầu truy cập khác của bạn dựa vào "thêm lần cuối" hay "ngày mới nhất", và sau đó cũng thường nếu bạn có ý định có thể thay đổi created_date như vậy hoặc thuộc tính "sắp xếp" khác theo cách sẽ ảnh hưởng đến thứ tự của các phần tử mảng khi được "sắp xếp".

Lý do bạn làm điều này sau đó khớp với mục "mới nhất" (hiện là "đầu tiên") trong mảng đơn giản trở thành:

$this->collection->find([
 'allotment_details.0.room_id': $this->RoomId
])

MongoDB cho phép chỉ định mảng "đầu tiên" được chỉ định bằng "Dấu chấm" , sử dụng 0 mục lục. Những gì bạn không thể do là chỉ định một chỉ mục "tiêu cực", tức là:

$this->collection->find([
 'allotment_details.-1.room_id': $this->RoomId  # not allowed :(
])

Đó là lý do tại sao bạn làm những việc được hiển thị ở trên khi "cập nhật" để "sắp xếp lại" mảng của bạn về dạng khả thi.

Kết nối không hợp lệ

Vấn đề chính khác là nối các chuỗi. Như đã đề cập, điều này tạo ra chi phí không cần thiết chỉ để thực hiện kết hợp bạn muốn. Nó cũng "không cần thiết" vì bạn có thể tránh điều này bằng cách sử dụng $ hoặc với các điều kiện trên mỗi trường như chúng đã tồn tại trong tài liệu thực tế:

 $this->collection->find([
   '$or' => [
       [ 'first_name' => new MongoDB\BSON\Regex($arg, 'i') ],
       [ 'last_name' => new MongoDB\BSON\Regex($arg, 'i') ],
       [ 'middle_name' => new MongoDB\BSON\Regex($arg, 'i') ],
       [ 'registration_temp_perm_no' => $arg ]
   ],
   'schoolId' => new MongoDB\BSON\ObjectID($this->SchoolId),
   'allotment_details.0.room_id': $this->RoomId
 ])

Và tất nhiên, bất kể điều kiện truy vấn "đầy đủ" thực sự cần là gì, nhưng bạn nên nắm được ý tưởng cơ bản.

Ngoài ra, nếu bạn không thực sự tìm kiếm "một phần từ", thì hãy "tìm kiếm văn bản" được xác định trên các trường có "tên". Sau khi tạo chỉ mục sẽ là:

 $this->collection->find([
   '$text' => [ '$search' => $arg ],
   'schoolId' => new MongoDB\BSON\ObjectID($this->SchoolId),
   'allotment_details.0.room_id': $this->RoomId
 ])

Nhìn chung, tôi thực sự khuyên bạn nên xem xét kỹ tất cả các tùy chọn khác hơn là thực hiện một thay đổi nhỏ đối với mã hiện tại của bạn. Với một chút cấu trúc lại cẩn thận về cách bạn lưu trữ mọi thứ và thực sự là "lập chỉ mục" mọi thứ, bạn sẽ nhận được những lợi ích hiệu suất to lớn mà $ concat mở rộng của bạn phương pháp tiếp cận "vũ phu" đơn giản là không thể mang lại hiệu quả.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Kích thước tối đa hoạt động hàng loạt MongoDB là gì?

  2. MongoDB như một dịch vụ hàng đợi?

  3. MongoDB Bound Queries:Làm cách nào để chuyển đổi dặm sang radian?

  4. Nhận một phần cụ thể của tài liệu

  5. Cách xóa tài liệu được trả về bởi một truy vấn tổng hợp trong mongodb