Sửa nhanh
"Đường ống dẫn" của bạn không hoạt động ở đây chủ yếu vì $ 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
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
và $ 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ả.