Saya seorang pemula yang diakui untuk API Entity, tetapi saya mencoba untuk menyembuhkannya. Saya sedang mengerjakan situs yang menggunakan sejumlah tipe konten dengan berbagai bidang yang menyertainya; tidak ada yang mewah. Jadi, ketika saya ingin mengambil satu set entri, saya, dalam ketidaktahuan saya, memanggil langsung ke dalam database dan melakukan sesuatu seperti ini:
$query = db_select('node', 'n')->extend('PagerDefault');
$query->fields('n', array('nid'));
$query->condition('n.type', 'my_content_type');
$query->leftJoin('field_data_field_user_role', 'role', 'n.nid = role.entity_id');
$query->condition('role.field_user_role_value', $some_value);
$query->leftJoin('field_data_field_withdrawn_time', 'wt', 'n.nid = wt.entity_id');
$query->condition('wt.field_withdrawn_time_value', 0);
$query->orderBy('n.created', 'desc');
$query->limit(10);
$result = $the_questions->execute()->fetchCol();
(ya, saya mungkin bisa menciutkan banyak baris ini menjadi satu $the_questions->
pernyataan; tolong abaikan itu untuk sekarang.)
Mencoba menulis ulang ini dengan EntityFieldQuery, saya datang dengan:
$query = new EntityFieldQuery();
$query
->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'my_content_type')
->fieldCondition('field_user_role', 'value', $some_value)
->fieldCondition('field_withdrawn_time', 'value', 0)
->propertyOrderBy('created', 'desc')
->pager(10);
$result = $query->execute();
if (isset($result['node'])) {
$result_nids = array_keys($result['node']);
}
else {
$result_nids = array();
}
yang memberi saya hasil yang diinginkan dan pasti jauh lebih cantik.
Jadi, sekarang saya bertanya-tanya tentang kinerja. Sebagai permulaan, saya membuang masing-masing bit kode ke dalam for()
loop bodoh , menangkap time()
sebelum dan sesudah eksekusi. Saya menjalankan setiap versi 100 kali melalui basis data yang tidak terlalu besar, dan mendapatkan sesuatu seperti ini:
- Versi langsung: 110 msec
- Versi EFQ: 4943 msec
Jelas saya mendapatkan hasil yang berbeda ketika saya menjalankan kembali tes, tetapi hasilnya konsisten di stadion baseball yang sama.
Astaga. Apakah saya melakukan sesuatu yang salah di sini, atau ini hanya biaya menggunakan EFQ? Saya belum melakukan penyetelan basis data khusus sehubungan dengan jenis konten; mereka hanya apa yang datang dari mendefinisikan tipe konten dengan cara biasa, berbasis form. Adakah pikiran? Kode EFQ jelas lebih bersih, tapi saya benar-benar tidak berpikir saya mampu menghasilkan hit kinerja 40x.
->addTag('node_access')
dalam kueri ??). Saya mengulangi permintaan "langsung" dengan tag node_access, dan waktu eksekusi lebih dekat: Waktu EFQ sekarang hanya sekitar faktor 2 lebih besar daripada pendekatan langsung, yang terlihat masuk akal mengingat SQL relatif yang keduanya pompakan (yang Saya dapat memposting jika orang masih peduli). (cont'd pada komentar berikutnya ....)Jawaban:
The
EntityFieldQuery
kelas seefisien persyaratan memungkinkan hal itu terjadi. Itu harus kompatibel dengan kelas penyimpanan bidang apa pun, bahkan dengan mereka yang menggunakan mesin NoSQL untuk menyimpan data lapangan, seperti yang menggunakan MongoDB . Karena alasan itu,EntityFieldQuery
tidak dapat secara langsung menanyakan database, karena backend penyimpanan bidang saat ini mungkin tidak menggunakan database SQL sama sekali.Bahkan dalam kasus penyimpanan lapangan menggunakan mesin SQL untuk menyimpan datanya, setara dengan
$query->leftJoin('field_data_field_user_role', 'role', 'n.nid = role.entity_id'); $query->condition('role.field_user_role_value', $some_value);
untukEntityFieldQuery
kelas membutuhkan:Perbedaannya langsung terlihat: Dalam satu kasus Anda menggunakan tiga string litteral, sedangkan dalam kasus lain ada kode yang (dalam kasus paling sederhana) adalah string yang menyambung.
Sesuai komentar Anda tentang kode yang memeriksa apakah pengguna memiliki izin untuk mengakses bidang, Anda dapat memotongnya menggunakan baris berikut ke kode menggunakan
EntityFieldQuery
kelas.Ini berfungsi jika Anda menggunakan Drupal 7.15, atau lebih tinggi; untuk versi sebelumnya, Anda harus menggunakan kode berikut.
Seperti biasa, Anda tidak boleh melewati izin akses jika kode dapat menunjukkan informasi pengguna yang tidak boleh diakses oleh pengguna. Ini mirip dengan apa yang dilakukan dari Drupal ketika simpul yang tidak diterbitkan hanya ditampilkan kepada pengguna yang memiliki izin untuk melihat simpul yang tidak diterbitkan. Jika tujuan kode adalah, misalnya, memilih beberapa entitas yang dihapus secara berurutan (misalnya selama tugas cron), maka dengan melewati kontrol akses tidak membahayakan, dan itu adalah satu-satunya cara untuk melanjutkan.
sumber
->extend('PagerDefault');
pada awalnya)