Ringkasan kueri Grafik Spanner

Dokumen ini menjelaskan cara membuat kueri grafik properti di Spanner Graph. Tujuan contoh di bagian ini menggunakan skema grafik yang Anda buat di Menyiapkan dan membuat kueri Spanner Graph, yang merupakan diilustrasikan dalam diagram berikut:

Contoh skema Grafik Spanner.

Menjalankan kueri Grafik Spanner

Anda dapat menjalankan kueri Spanner Graph dengan cara berikut:

Struktur kueri Grafik Spanner

Bagian ini menjelaskan setiap komponen kueri secara mendetail.

Contoh berikut mengilustrasikan struktur dasar Grafik Spanner kueri.

Contoh struktur kueri Spanner Graph.

Spanner Graph memungkinkan Anda membuat beberapa grafik di dalam database. Kueri dimulai dengan menentukan grafik target, FinGraph, menggunakan klausa GRAPH.

Pencocokan pola grafik

Pencocokan pola grafik menemukan pola tertentu dalam grafik Anda. Yang paling dasar adalah Pola elemen (pola node dan pola tepi), yang cocok dengan grafik elemen (masing-masing simpul dan tepi). Pola elemen dapat disusun menjadi pola jalur dan pola yang lebih kompleks.

Pola node

Pola node adalah pola yang mencocokkan node dari grafik Anda. Pola ini terdiri dari sepasang tanda kurung yang cocok, yang mungkin secara opsional berisi variabel pola grafik, ekspresi label, dan filter properti.

Menemukan semua node

Kueri berikut menampilkan semua node dalam grafik. Variabel n, yang disebut variabel pola grafik, yang akan diikat ke node yang cocok. Dalam hal ini, {i>node<i} cocok dengan semua node dalam grafik.

GRAPH FinGraph
MATCH (n)
RETURN LABELS(n) AS label, n.id;

Hasil

Kueri tersebut menampilkan label dan id sebagai berikut:

label id
Akun 7
Akun 16
Akun 20
Orang 1
Orang 2
Orang 3

Menemukan semua node dengan label tertentu

Kueri berikut cocok dengan semua node dalam grafik yang memiliki Person label. Kueri tersebut menampilkan properti label dan id, name dari node yang cocok.

GRAPH FinGraph
MATCH (p:Person)
RETURN LABELS(p) AS label, p.id, p.name;

Hasil

label id nama
Orang 1 Alex
Orang 2 Dana
Orang 3 Lee

Temukan semua node yang cocok dengan ekspresi label

Anda dapat membuat ekspresi label dengan satu atau beberapa operator logika.

Kueri berikut cocok dengan semua node dalam grafik yang memiliki Label Person atau Account. Serangkaian properti yang diekspos oleh variabel pola grafik n adalah superset dari properti yang diekspos oleh node yang memiliki label Person atau Account.

GRAPH FinGraph
MATCH (n:Person|Account)
RETURN LABELS(n) AS label, n.id, n.birthday, n.create_time;
  • Dalam hasilnya, semua node memiliki properti id.
  • Node yang cocok dengan label Account memiliki properti create_time, tetapi tidak memiliki properti birthday. NULL ditampilkan untuk properti birthday untuk node tersebut.
  • Node yang cocok dengan label Person memiliki properti birthday, tetapi tidak memiliki properti create_time. NULL ditampilkan untuk create_time untuk node tersebut.

Hasil

label id ulang tahun create_time
Akun 7 NULL 2020-01-10T14:22:20.222Z
Akun 16 NULL 2020-01-28T01:55:09.206Z
Akun 20 NULL 2020-02-18T13:44:20.655Z
Orang 1 1991-12-21T08:00:00Z NULL
Orang 2 1980-10-31T08:00:00Z NULL
Orang 3 1986-12-07T08:00:00Z NULL

Untuk informasi selengkapnya tentang aturan ekspresi label, lihat Ekspresi label.

Temukan semua node yang cocok dengan ekspresi label dan filter properti

Kueri berikut cocok dengan semua node dalam grafik yang memiliki label Person, dan yang properti id sama dengan 1.

GRAPH FinGraph
MATCH (p:Person {id: 1})
RETURN LABELS(p) AS label, p.id, p.name, p.birthday;

Hasil

label id nama ulang tahun
Orang 1 Alex 1991-12-21T08:00:00Z

Anda dapat menggunakan klausa WHERE untuk membentuk kondisi pemfilteran yang lebih kompleks di label dan properti.

Kueri berikut cocok dengan semua node dalam grafik yang memiliki Person label, dan properti birthday adalah sebelum 1990-01-10.

GRAPH FinGraph
MATCH (p:Person WHERE p.birthday < '1990-01-10')
RETURN LABELS(p) AS label, p.name, p.birthday;

Hasil

label nama ulang tahun
Orang Dana 1980-10-31T08:00:00Z
Orang Lee 1986-12-07T08:00:00Z

Pola tepi

Pola tepi cocok dengan tepi atau hubungan antar-node. Pola tepi adalah diapit dengan tanda kurung siku [] dengan simbol -, ->, atau <- untuk menunjukkan petunjuk arah.

Serupa dengan pola {i>node<i}, variabel pola grafik digunakan untuk mengikat ke tepi yang sesuai yang kurang penting.

Menemukan semua tepi dengan label yang cocok

Kueri berikut menampilkan semua tepi dalam grafik yang memiliki label Owns. Variabel pola grafik e terikat dengan tepi yang cocok.

GRAPH FinGraph
MATCH -[e:Owns]->
RETURN e.id AS owner_id, e.account_id;

Hasil

owner_id id_akun
1 7
3 16
2 20

Temukan semua tepi yang cocok dengan ekspresi label dan filter properti

Mirip dengan pola {i>node<i}, pola tepi dapat menggunakan ekspresi label, spesifikasi properti, dan klausa WHERE, seperti yang ditunjukkan dalam kueri berikut. Kueri menemukan semua tepi yang diberi label dengan Owns dan memiliki properti create_time dalam periode tertentu.

GRAPH FinGraph
MATCH -[e:Owns WHERE e.create_time > '2020-01-14'
                 AND e.create_time < '2020-05-14']->
RETURN e.id AS owner_id, e.create_time, e.account_id;

Hasil

owner_id create_time id_akun
2 2020-01-28T01:55:09.206Z 20
3 2020-02-18T13:44:20.655Z 16

Cari semua tepi menggunakan pola tepi arah mana saja

Meskipun semua edge di Spanner Graph telah diarahkan, Anda dapat menggunakan Pola tepi any direction -[]- dalam kueri untuk mencocokkan tepi di salah satu arah.

Kueri berikut menemukan semua transfer yang melibatkan akun yang diblokir.

GRAPH FinGraph
MATCH (account:Account)-[transfer:Transfers]-(:Account)
WHERE account.is_blocked
RETURN transfer.order_number, transfer.amount;

Hasil

order_number jumlah
304330008004315 300
304120005529714 100
103650009791820 300
302290001255747 200

Pola jalur

Pola jalur dibuat dari pola simpul dan tepi yang berselang-seling.

Menemukan semua jalur dari node dengan label dan filter properti yang ditentukan, menggunakan pola jalur

Kueri berikut menemukan semua transfer ke akun yang dimulai dari akun dimiliki oleh Person dengan id yang sama dengan 2.

Setiap hasil yang cocok mewakili jalur dari Person {id: 2} melalui menghubungkan Account menggunakan tepi Owns, ke Account lain menggunakan tepi Transfers.

GRAPH FinGraph
MATCH
  (p:Person {id: 2})-[:Owns]->(account:Account)-[t:Transfers]->
  (to_account:Account)
RETURN
  p.id AS sender_id, account.id AS from_id, to_account.id AS to_id;

Hasil

sender_id from_id to_id
2 20 7
2 20 16

Pola jalur terukur

Pola terukur memungkinkan sebuah pola diulang dalam rentang tertentu.

Mencocokkan pola tepi terukur

Kueri berikut menemukan semua akun tujuan satu hingga tiga transfer dari sumber Account dengan id yang sama dengan 7, selain itu sendiri.

Pola tepi diposting dengan penghitung {1, 3}.

GRAPH FinGraph
MATCH (src:Account {id: 7})-[e:Transfers]->{1, 3}(dst:Account)
WHERE src != dst
RETURN src.id AS src_account_id, ARRAY_LENGTH(e) AS path_length, dst.id AS dst_account_id;

Hasil

src_account_id path_length dst_account_id
7 1 16
7 1 16
7 1 16
7 3 16
7 3 16
7 2 20
7 2 20

Contoh sebelumnya menggunakan fungsi ARRAY_LENGTH untuk mengakses group variable e Sebagai informasi selengkapnya, lihat variabel grup akses.

Beberapa baris dalam contoh hasil diulang karena mungkin ada beberapa jalur antara pasangan akun src dan dst yang sama yang cocok dengan pola tersebut.

Mencocokkan pola jalur terukur

Kueri berikut menemukan jalur di antara node Account dengan satu hingga dua Transfers melalui akun perantara yang diblokir.

Pola jalur dalam tanda kurung dikuantifikasi dan klausa WHERE digunakan dalam tanda kurung untuk menentukan kondisi bagi pola berulang.

GRAPH FinGraph
MATCH
  (src:Account)
  ((:Account)-[:Transfers]->(interm:Account) WHERE interm.is_blocked){1,2}
    -[:Transfers]->(dst:Account)
RETURN src.id AS src_account_id, dst.id AS dst_account_id;

Hasil

src_account_id dst_account_id
7 20
7 20
20 20

Mengelompokkan variabel

Variabel pola grafik yang dideklarasikan dalam pola terukur dianggap sebagai variabel grup ketika diakses di luar pola terukur, dan mengikat ke elemen grafik yang cocok.

Anda dapat mengakses variabel grup sebagai array tempat elemen grafik dipertahankan dalam urutan tampilan di sepanjang jalur yang cocok. Anda dapat menggabungkan grup variabel menggunakan agregasi horizontal.

Variabel grup akses

Pada contoh berikut, variabel e diakses sebagai berikut:

  • Variabel pola grafik yang terikat dengan satu tepi dalam klausa WHERE e.amount > 100 (dalam pola terukur).
  • Variabel grup yang terikat ke array elemen edge di ARRAY_LENGTH(e) dalam pernyataan RETURN (di luar pola terukur).
  • Variabel grup yang terikat ke array elemen edge, yang digabungkan oleh SUM(e.amount) di luar pola terukur. Ini adalah contoh agregasi horizontal.
GRAPH FinGraph
MATCH
  (src:Account {id: 7})-[e:Transfers WHERE e.amount > 100]->{0,2}
  (dst:Account)
WHERE src.id != dst.id
LET total_amount = SUM(e.amount)
RETURN
  src.id AS src_account_id, ARRAY_LENGTH(e) AS path_length,
  total_amount, dst.id AS dst_account_id;

Hasil

src_account_id path_length total_amount dst_account_id
7 1 300 16
7 2 600 20

Setiap dan Setiap Jalur Terpendek

Untuk membatasi jalur yang cocok di setiap grup jalur yang berbagi sumber dan node tujuan, Anda dapat menggunakan awalan penelusuran jalur ANY atau ANY SHORTEST. Anda hanya dapat menerapkan awalan ini sebelum seluruh pola jalur, dan Anda tidak dapat menerapkannya di dalam tanda kurung.

Cocokkan menggunakan APA PUN

Kueri berikut menemukan semua akun unik yang dapat dijangkau, yaitu satu atau dua Transfers dari node Account tertentu.

Awalan penelusuran jalur ANY memastikan bahwa hanya satu jalur di antara jalur unik pasangan node src dan dst Account ditampilkan. Dalam contoh berikut, meskipun Anda dapat menjangkau node Account dengan {id: 16} dalam dua jalur dari node Account sumber, hasilnya hanya mencakup satu jalur.

GRAPH FinGraph
MATCH ANY (src:Account {id: 7})-[e:Transfers]->{1,2}(dst:Account)
LET ids_in_path = ARRAY(SELECT e.to_id FROM UNNEST(e) AS e)
RETURN src.id AS src_account_id, dst.id AS dst_account_id, ids_in_path;

Hasil

src_account_id dst_account_id ids_in_path
7 16 16
7 20 16,20.

Membuat grafik pola

Pola grafik terdiri dari satu atau beberapa pola jalur, yang dipisahkan oleh koma ,. Pola grafik dapat berisi klausa WHERE, yang memungkinkan Anda mengakses semua membuat grafik variabel pola dalam pola jalur untuk membentuk kondisi pemfilteran. Setiap jalur yang menghasilkan sekumpulan jalur.

Cocokkan menggunakan pola grafik

Kueri berikut mengidentifikasi akun perantara dan pemiliknya yang terlibat dengan jumlah transaksi melebihi 200, yang akan digunakan untuk mentransfer dana dari akun sumber ke akun yang diblokir.

Pola jalur berikut membentuk pola grafik:

  • Pola pertama menemukan jalur di mana transfer terjadi dari satu ke akun yang diblokir menggunakan akun perantara.
  • Pola kedua menemukan jalur dari sebuah akun ke pengguna yang memilikinya.

Variabel interm bertindak sebagai tautan umum antara dua pola jalur, yang memerlukan interm untuk mereferensikan node elemen yang sama di kedua pola jalur. Ini membuat operasi equi-join berdasarkan variabel interm.

GRAPH FinGraph
MATCH
  (src:Account)-[t1:Transfers]->(interm:Account)-[t2:Transfers]->(dst:Account),
  (interm)<-[:Owns]-(p:Person)
WHERE dst.is_blocked = TRUE AND t1.amount > 200 AND t2.amount > 200
RETURN
  src.id AS src_account_id, dst.id AS dst_account_id,
  interm.id AS interm_account_id, p.id AS owner_id;

Hasil

src_account_id dst_account_id interm_account_id owner_id
20 16 7 1

Pernyataan kueri linear

Anda dapat merangkai beberapa pernyataan grafik bersama-sama untuk membentuk pernyataan kueri linear. Pernyataan dieksekusi dalam urutan yang sama seperti yang muncul dalam kueri.

  • Setiap pernyataan mengambil output dari pernyataan sebelumnya sebagai input. Tujuan input untuk pernyataan pertama kosong.
  • {i>Output<i} dari pernyataan terakhir adalah hasil akhir.

Menemukan transfer maksimum ke akun yang diblokir

Kueri berikut menemukan akun dan pemiliknya dengan traffic keluar terbesar mentransfer ke akun yang diblokir.

GRAPH FinGraph
MATCH (src_account:Account)-[transfer:Transfers]->(dst_account:Account)
WHERE dst_account.is_blocked
ORDER BY transfer.amount DESC
LIMIT 1
MATCH (src_account:Account)<-[owns:Owns]-(owner:Person)
RETURN src_account.id AS account_id, owner.name AS owner_name;

Tabel berikut mengilustrasikan cara hasil perantara diteruskan pernyataan-pernyataan tersebut. Hanya beberapa properti dari hasil perantara yang ditampilkan, untuk ringkas.

Pernyataan Hasil Menengah (disingkat)
MATCH
  (src_account:Account)
    -[transfer:Transfers]->
  (dst_account:Account)
WHERE dst_account.is_blocked
src_account transfer dst_account
{id: 7} {amount: 300.0} {id: 16, is_blocked: true}
{id: 7} {amount: 100.0} {id: 16, is_blocked: true}
{id: 20} {amount: 200.0} {id: 16, is_blocked: true}

ORDER BY transfer.amount DESC
src_account transfer dst_account
{id: 7} {amount: 300.0} {id: 16, is_blocked: true}
{id: 20} {amount: 200.0} {id: 16, is_blocked: true}
{id: 7} {amount: 100.0} {id: 16, is_blocked: true}

LIMIT 1
src_account transfer dst_account
{id: 7} {amount: 300.0} {id: 16, is_blocked: true}

MATCH
  (src_account:Account)
    <-[owns:Owns]-
  (owner:Person)
src_account transfer dst_account memiliki pemilik
{id: 7} {amount: 300.0} {id: 16, is_blocked: true} {person_id: 1, account_id: 7} {id: 1, name: Alex}

RETURN
  src_account.id AS account_id,
  owner.name AS owner_name
account_id owner_name
7 Alex

Hasil

id_akun owner_name
7 Alex

Laporan pengembalian

Pernyataan return menentukan apa yang akan ditampilkan dari pola yang cocok. Dapat mengakses variabel pola grafik, berisi ekspresi dan klausa lain seperti ORDER_BY, GROUP_BY. Lihat pernyataan RETURN.

Perhatikan bahwa Spanner Graph tidak mendukung menampilkan elemen grafik sebagai kueri hasil pengujian tersebut. Untuk menampilkan seluruh elemen grafik, gunakan fungsi TO_JSON.

Menampilkan elemen grafik sebagai JSON

GRAPH FinGraph
MATCH (n:Account {id: 7})
-- Returning a graph element in the final results is NOT allowed. Instead, use
-- the TO_JSON function or explicitly return the graph element's properties.
RETURN TO_JSON(n) AS n;

Hasil

n
{&quot;identifier&quot;:&quot;mUZpbkdyYXBoLkFjY291bnQAeJEO&quot;,&quot;kind&quot;:&quot;node&quot;,&quot;labels&quot;:[&quot;Account&quot;],&quot;properties&quot;:{&quot;create_time&quot;:&quot;2020-01-10T14:22:20.222Z&quot;,&quot;id&quot;:7,&quot;is_blocked&quot;:false,&quot;nick_name&quot;:&quot;Vacation Dana"}}

Menulis kueri yang lebih besar dengan kata kunci NEXT

Anda dapat menggabungkan beberapa pernyataan kueri grafik linear menggunakan NEXT kata kunci. Input ke pernyataan kueri linear pertama kosong. Output dari setiap pernyataan kueri linear menjadi {i>input<i} ke pernyataan kueri linear berikutnya.

Contoh berikut menemukan pemilik akun dengan permintaan masuk terbanyak transfer dengan merangkai beberapa pernyataan linear grafik bersama-sama. Perlu diperhatikan bahwa Anda dapat menggunakan variabel yang sama, account dalam contoh ini, untuk merujuk ke grafik yang sama di beberapa pernyataan linear.

GRAPH FinGraph
MATCH (:Account)-[:Transfers]->(account:Account)
RETURN account, COUNT(*) AS num_incoming_transfers
GROUP BY account
ORDER BY num_incoming_transfers DESC
LIMIT 1

NEXT

MATCH (account:Account)<-[:Owns]-(owner:Person)
RETURN account.id AS account_id, owner.name AS owner_name, num_incoming_transfers;

Hasil

id_akun owner_name num_incoming_transfers
16 Lee 3

Fungsi dan ekspresi

Anda dapat menggunakan semua fungsi, operator, dan kondisional di GoogleSQL, termasuk fungsi agregat dan fungsi skalar lainnya dalam kueri Spanner Graph.

Spanner Graph juga mendukung operator dan fungsi bawaan untuk elemen grafik.

Fungsi dan operator bawaan

Fungsi berikut dan operator biasa digunakan dalam GQL:

  • PROPERTY_EXISTS(n, birthday): Menampilkan apakah n menampilkan birthday saat ini.
  • LABELS(n): Menampilkan label n seperti yang ditentukan dalam skema grafik.
  • PROPERTY_NAMES(n): Menampilkan nama properti n.
  • TO_JSON(n): Menampilkan n dalam format JSON. Untuk informasi selengkapnya, lihat Fungsi TO_JSON.

Kueri berikut mengilustrasikan predikat PROPERTY_EXISTS,fungsi LABELS, dan TO_JSON, serta fungsi bawaan lainnya seperti ARRAY_AGG dan CONCAT.

GRAPH FinGraph
MATCH (person:Person)-[:Owns]->(account:Account)
RETURN person, ARRAY_AGG(account.nick_name) AS accounts
GROUP BY person

NEXT

RETURN
  LABELS(person) AS labels,
  TO_JSON(person) AS person,
  accounts,
  CONCAT(person.city, ", ", person.country) AS location,
  PROPERTY_EXISTS(person, is_blocked) AS is_blocked_property_exists,
  PROPERTY_EXISTS(person, name) AS name_property_exists
LIMIT 1;

Hasil

is_blocked_property_exists name_property_exists label akun location pengguna
salah benar Orang ["Dana Liburan"] Adelaide, Australia {&quot;identifier&quot;:&quot;mUZpbkdyYXBoLlBlcnNvbgB4kQI=&quot;,&quot;kind&quot;:&quot;node&quot;,&quot;labels&quot;:[&quot;Person&quot;],&quot;properties&quot;:{&quot;birthday&quot;:&quot;1991-12-21T08:00:00Z&quot;,&quot;city&quot;:&quot;Adelaide&quot;,&quot;country&quot;:&quot;Australia&quot;,&quot;id&quot;:1,&quot;name&quot;:&quot;Alex&quot;}}

Subkueri

Subquery adalah kueri yang disusun bertingkat dalam kueri lainnya. Daftar berikut Aturan subkueri Grafik Spanner:

  • Subkueri dimasukkan dalam sepasang tanda kurung kurawal {}.
  • Subkueri dapat dimulai dengan klausa GRAPH di awal untuk menentukan grafik dalam cakupan. Grafik yang ditentukan tidak harus sama dengan yang yang digunakan dalam kueri {i>outer<i}.
  • Jika klausa GRAPH dihilangkan dalam subkueri, hal berikut akan terjadi:
    • Grafik dalam cakupan disimpulkan dari konteks kueri {i>outer<i} yang terdekat.
    • Sub kueri harus dimulai dari pernyataan pencocokan pola grafik dengan MATCH.
  • Variabel pola grafik yang dideklarasikan di luar cakupan subkueri tidak dapat dideklarasikan lagi di dalam sub kueri, tetapi dapat dirujuk di atau fungsi di dalam sub kueri.

Gunakan subkueri untuk menemukan jumlah total transfer dari setiap akun

Kueri berikut mengilustrasikan penggunaan subkueri VALUE. Sub kuerinya adalah diapit dalam tanda kurung kurawal {} yang diawali dengan kata kunci VALUE. Kueri tersebut mengembalikan total jumlah transfer yang dilakukan dari sebuah akun.

GRAPH FinGraph
MATCH (p:Person)-[:Owns]->(account:Account)
RETURN p.name, account.id AS account_id, VALUE {
  MATCH (a:Account)-[transfer:Transfers]->(:Account)
  WHERE a = account
  RETURN SUM(transfer.amount) AS total_transfer
} AS total_transfer;

Hasil

nama id_akun total_transfer
Alex 7 400
Dana 20 700
Lee 16 300

Untuk daftar ekspresi subkueri yang didukung, lihat subkueri Grafik Spanner.

Parameter kueri

Anda dapat membuat kueri Spanner Graph dengan parameter. Untuk informasi selengkapnya, lihat sintaksis dan mempelajari cara data kueri dengan parameter di library klien Spanner.

Kueri berikut mengilustrasikan penggunaan parameter kueri.

GRAPH FinGraph
MATCH (person:Person {id: @id})
RETURN person.name;

Membuat kueri grafik dan tabel bersama-sama

Anda dapat menggunakan kueri Graph bersamaan dengan SQL untuk mengakses informasi dari Grafik dan Tabel Anda bersama-sama dalam satu pernyataan.

GRAPH_TABLE

Operator GRAPH_TABLE mengambil kueri grafik linear dan menampilkan hasilnya di bentuk tabel yang dapat diintegrasikan dengan lancar ke dalam kueri SQL. Ini interoperabilitas memungkinkan Anda memperkaya hasil kueri grafik dengan konten non-grafik dan sebaliknya.

Misalnya, Anda dapat membuat tabel CreditReports dan memasukkan beberapa kredit seperti yang ditunjukkan dalam contoh berikut:

CREATE TABLE CreditReports (
  person_id     INT64 NOT NULL,
  create_time   TIMESTAMP NOT NULL,
  score         INT64 NOT NULL,
) PRIMARY KEY (person_id, create_time);
INSERT INTO CreditReports (person_id, create_time, score)
VALUES
  (1,"2020-01-10 06:22:20.222", 700),
  (2,"2020-02-10 06:22:20.222", 800),
  (3,"2020-03-10 06:22:20.222", 750);

Kemudian, identifikasi orang yang diminati melalui pencocokan pola grafik di GRAPH_TABLE dan gabungkan hasil kueri grafik dengan tabel CreditReports untuk mengakses kredit skor.

SELECT
  gt.person.id,
  credit.score AS latest_credit_score
FROM GRAPH_TABLE(
  FinGraph
  MATCH (person:Person)-[:Owns]->(:Account)-[:Transfers]->(account:Account)
  WHERE account.is_blocked
  RETURN DISTINCT person
) AS gt
JOIN CreditReports AS credit
  ON gt.person.id = credit.person_id
ORDER BY credit.create_time;

Hasil:

person_id latest_credit_score
1 700
2 800

Langkah selanjutnya

Pelajari praktik terbaik untuk menyesuaikan kueri.