Perbaikan cepat
"Pipa" Anda tidak berfungsi di sini terutama karena $project
awal Anda
tidak memiliki bidang yang ingin Anda gunakan di tahap selanjutnya. "Perbaikan cepat" oleh karena itu pada dasarnya untuk memasukkan bidang itu ke dalam dokumen "yang diproyeksikan", karena itulah cara kerja tahapan pipa agregasi:
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
)
),
Atau bahkan sejak Anda menggunakan $$ROOT
untuk Siswa
bagaimanapun, cukup kualifikasi bidang di bawah jalur itu:
'$expr' => array(
'$eq'=> array(
array('$arrayElemAt' => array('$Student.allotment_details.room_id', -1)),
$this->RoomId
)
),
namun Saya akan sangat* mohon agar Anda TIDAK lakukan itu.
Seluruh konsep "penggabungan string" untuk melakukan $cocok
pada konten adalah ide yang sangat buruk karena itu berarti seluruh koleksi akan ditulis ulang dalam alur sebelum "pemfilteran" benar-benar dilakukan.
Demikian juga mencari kecocokan pada elemen array "terakhir" juga merupakan masalah. Pendekatan yang jauh lebih baik adalah dengan benar-benar menambahkan "item baru" ke "awal" array, alih-alih "akhir". Ini sebenarnya yang $position
atau bahkan mungkin $sort
pengubah ke $push
lakukan untuk Anda, dengan mengubah tempat item ditambahkan atau urutan item yang diurutkan masing-masing.
Mengubah Array menjadi "terbaru dulu"
Ini membutuhkan sedikit kerja dengan mengubah cara Anda menyimpan sesuatu, tetapi manfaatnya adalah peningkatan kecepatan kueri seperti yang Anda inginkan tanpa memerlukan $expr
yang dievaluasi argumen.
Konsep inti adalah untuk "menangguhkan" item array baru dengan sintaks seperti:
$this->collection->updateOne(
$query,
[ '$push' => [ 'allotment_details' => [ '$each' => $allotments, '$position' => 0 ] ] ]
)
Dimana $alloments
harus menjadi array seperti yang dipersyaratkan oleh $each
dan $position
digunakan untuk 0
untuk menambahkan item array baru "pertama".
Atau jika Anda benar-benar memiliki sesuatu seperti created_date
sebagai properti di dalam setiap objek dalam array, maka Anda "bisa" menggunakan sesuatu seperti $sort
sebagai pengubah.
$this->collection->updateOne(
$query,
[ '$push' => [
'allotment_details' => [ '$each' => $allotments, '$sort' => [ 'created_date' => -1 ] ]
]]
)
Itu benar-benar tergantung pada apakah "kueri" Anda dan persyaratan akses lainnya bergantung pada "terakhir ditambahkan" atau "tanggal terbaru", dan kemudian juga biasanya jika Anda berniat untuk mengubah created_date
tersebut. atau properti "sort" lainnya dengan cara yang akan mempengaruhi urutan elemen array saat "diurutkan".
Alasan Anda melakukan ini adalah mencocokkan item "terbaru" ( yang sekarang menjadi "pertama" ) dalam array menjadi:
$this->collection->find([
'allotment_details.0.room_id': $this->RoomId
])
MongoDB memungkinkan indeks array "pertama" ditentukan dengan "Notasi Titik"
, menggunakan 0
indeks. Apa yang Anda tidak bisa lakukan adalah menentukan indeks "negatif" yaitu:
$this->collection->find([
'allotment_details.-1.room_id': $this->RoomId # not allowed :(
])
Itulah alasan mengapa Anda melakukan hal-hal yang ditunjukkan di atas pada "pembaruan" untuk "mengurutkan ulang" array Anda ke bentuk yang bisa diterapkan.
Penggabungan buruk
Masalah utama lainnya adalah penggabungan string. Seperti yang telah disebutkan, ini menciptakan overhead yang tidak perlu hanya untuk melakukan pencocokan yang Anda inginkan. Ini juga "tidak perlu" karena Anda dapat menyelesaikan menghindari ini menggunakan $or
dengan kondisi pada masing-masing bidang seperti yang sudah ada dalam dokumen aktual:
$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
])
Dan tentu saja, apa pun kondisi kueri "penuh" yang sebenarnya diperlukan, tetapi Anda harus mendapatkan ide dasarnya.
Juga jika Anda tidak benar-benar mencari "kata sebagian", maka "pencarian teks" didefinisikan di atas bidang dengan "nama". Setelah membuat indeks yang akan menjadi:
$this->collection->find([
'$text' => [ '$search' => $arg ],
'schoolId' => new MongoDB\BSON\ObjectID($this->SchoolId),
'allotment_details.0.room_id': $this->RoomId
])
Secara keseluruhan, saya sangat merekomendasikan untuk melihat lebih dekat semua opsi lain daripada membuat satu perubahan kecil pada kode Anda yang ada. Dengan sedikit penataan ulang yang hati-hati tentang cara Anda menyimpan sesuatu dan memang "mengindeks" sesuatu, Anda mendapatkan manfaat kinerja yang sangat besar yang $concat
ekstensif Anda Pendekatan "brute force" tidak bisa dilakukan.