GraphQL: Cara Mendayakan Penapisan Senarai Arbitrari dengan Sift.js.

王林
Lepaskan: 2024-08-05 20:07:20
asal
329 orang telah melayarinya

GraphQL: How to Enable Arbitrary List Filtering with Sift.js.

Artikel Asal

Selalunya, terdapat jenis data senarai dalam skema GraphQL anda dan keperluan biasa ialah menapis senarai berdasarkan beberapa pembolehubah input. Penapisan ialah ciri penting yang membolehkan pengguna mendapatkan semula data yang mereka perlukan sahaja, menjadikan aplikasi lebih cekap dan mesra pengguna.

Terdapat banyak perpustakaan dan sumber tersedia untuk penapisan apabila menggunakan sumber data luaran yang menyokong pertanyaan, seperti Prisma di hadapan pangkalan data. Walau bagaimanapun, apabila menulis penyelesai anda sendiri yang mengembalikan senarai objek GraphQL, adalah berfaedah untuk mengabstrak logik penapisan dan menjadikannya boleh digunakan semula merentas skema anda.

Mari kita pertimbangkan skema GraphQL yang mudah untuk senarai buku:

type Book {
  title: String
  price: Float
}

type Query {
  books: [Book]
}
Salin selepas log masuk

Dan penyelesai berikut yang mengembalikan senarai buku daripada senarai ringkas. Ini boleh jadi mana-mana sumber data.

const books = [
  { title: 'The Great Gatsby', price: 10.99 },
  { title: 'To Kill a Mockingbird', price: 12.99 },
  // more books
];

const resolvers = {
  Query: {
    books: () => books,
  },
};
Salin selepas log masuk

Untuk contoh kita, mari kita anggap pengguna perlu menapis buku berdasarkan kriteria berikut:

  • Bermula dengan tajuk apa

  • Harga berada dalam julat, kurang daripada dan lebih besar daripada

Cara Mentakrifkan Penapis dan Logik Individu dalam GraphQL

Satu cara untuk melaksanakan penapis adalah dengan mentakrifkan setiap satu secara individu. Ini melibatkan membuat perubahan pada jenis input skema GraphQL dan melaksanakan penapis dalam logik penyelesai.

Anda boleh mengemas kini skema anda untuk memasukkan pembolehubah input baharu ini, membolehkan anda menyatakan penapis yang dibenarkan dan parameter yang diperlukan untuk menggunakannya:

input BookFilter {
  titleStartsWith: String
  priceLessThan: Float
  priceGreaterThan: Float
}

type Query {
  books(filter: BookFilter): [Book]
}
Salin selepas log masuk

Penyelesai yang dikemas kini mungkin kelihatan seperti ini:

const resolvers = {
  Query: {
    books: (_, { filter }) => {
      return books.filter(book => {
        if (filter.titleStartsWith && !book.title.startsWith(filter.titleStartsWith)) {
          return false;
        }
        if (filter.priceLessThan !== undefined && book.price >= filter.priceLessThan) {
          return false;
        }
        if (filter.priceGreaterThan !== undefined && book.price <= filter.priceGreaterThan) {
          return false;
        }
        return true;
      });
    },
  },
};
Salin selepas log masuk

Membuat pertanyaan dengan sintaks ini agak mudah difahami. Anda akan membekalkan hujah penapis kepada penyelesai GraphQL, memberikan nilai untuk medan input penapis tersebut jika diperlukan.

Faedah Pendekatan Ini

Hanya penapis yang anda mahu benarkan pengguna gunakan disokong.

Ini disokong oleh sistem pengesahan jenis GraphQL, yang tidak akan membenarkan penapisan di luar apa yang dibenarkan. Kod penyelesai di bahagian belakang itu sendiri tidak menyokong penapis yang tidak dibenarkan.

Kelemahan Pendekatan Ini

Anda perlu menentukan setiap penapis secara individu dalam skema GraphQL dan dalam pelaksanaan dalam kod.

Anda tidak boleh berkongsi kod ini dengan mudah antara objek GraphQL yang berbeza. Jika anda juga mempunyai Video dan ingin menapisnya, ia memerlukan jenis input penapisan baharu untuk video. (Anda boleh membuat generalisasi kepada input penapis, tetapi kemudian Buku dan Video tidak boleh berbeza.)

Jika terdapat keperluan untuk penapis baharu, ia memerlukan perubahan kod untuk ditambahkan pada jenis penapis input dan untuk mengemas kini kod penyelesai untuk menyokongnya.

Cth., jika anda ingin menapis tajuk yang menyertakan subrentetan di mana-mana sahaja, bukan sahaja pada permulaan, ini ialah input penapis baharu dan pelaksanaan baharu dalam penyelesai anda.

Penapisan Arbitrari dengan Menerima Bahasa Pertanyaan Ayak sebagai Input Penapis

Pustaka menarik yang saya temui, menapis, membenarkan penggunaan sintaks pertanyaan MongoDB untuk menapis senarai data sewenang-wenang dengan mudah dalam JavaScript. Saya rasa ini sangat bagus dan boleh mendayakan penapisan sewenang-wenang dalam GraphQL. CMS Strapi tanpa kepala sebelum ini menggunakan Sift sebelum beralih kepada penyelesaian yang lebih tersuai untuk membolehkan pertanyaan GraphQL mereka!

Saya amat teruja dengan perkara ini kerana ia nampaknya merupakan satu cara untuk menghasilkan semula penapisan automatik berguna yang telah dibina oleh sesetengah ORM dan penyedia dalam perkhidmatan GraphQL mereka. Dan tidak mengapa jika data itu tidak datang dari pangkalan data tertentu.

Anda boleh menulis semula skema di atas kepada yang berikut:

input SiftQueryInput {
  field: String
  filter: String
}

type Query {
  books(filter: [SiftQueryInput]): [Book]
}
Salin selepas log masuk

Dan penyelesai kepada:

const sift = require('sift').default;

const resolvers = {
  Query: {
    books: (_, { filter }) => {
      const siftQuery = filter.reduce((acc, { field, filter }) => {
        acc[field] = JSON.parse(filter);
        return acc;
      }, {});
      return books.filter(sift(siftQuery));
    },
  },
};
Salin selepas log masuk

Jadi bagaimana ini berfungsi? Katakan anda ingin menanyakan semua buku yang bermula dengan 'The'. Anda boleh melaksanakan pertanyaan ini:

query {
  books(filter: [{ field: "title", filter: "{\"$regex\": \"^The\"}" }]) {
    title
    price
  }
}
Salin selepas log masuk

Dengan pembolehubah ini:

{
  "filter": [
    { "field": "title", "filter": "{\"$regex\": \"^The\"}" }
  ]
}
Salin selepas log masuk

Dan seperti yang dijangkakan, anda akan mendapatkan kembali senarai yang ditapis kepada 'The Great Gatsby'!

Contoh lain, jika anda ingin menapis buku yang mengandungi huruf 'i' dan harganya lebih besar daripada 10, anda akan membekalkan pembolehubah berikut:

{
  "filter": [
    { "field": "title", "filter": "{\"$regex\": \"i\"}" },
    { "field": "price", "filter": "{\"$gt\": 10}" }
  ]
}
Salin selepas log masuk

Dan anda mendapat kembali buku 'To Kill a Mockingbird'!

Perhatikan bahawa kami tidak perlu mengubah apa-apa dalam pertanyaan, skema atau penyelesai! Kami dapat menyatakan penapis baharu sepenuhnya yang memerlukan input penapis baharu dalam pendekatan lain, hanya dalam pembolehubah menggunakan sintaks pertanyaan Ayak!

Faedah Pendekatan Ini

Sebarang logik penapisan yang disokong Sift kini boleh dinyatakan dalam pertanyaan anda. Jika keperluan baharu masuk untuk penapis yang berbeza, ia tidak memerlukan pengemaskinian dengan jenis input baharu dan logik penyelesai.

Kaedah penapisan yang sama boleh digunakan merentas semua jenis anda! Hanya menerima senarai SiftQueryInputs dan pelaksanaan bahagian belakang untuk mengendalikan input Ayak tersebut dan menerapkannya pada senarai objek tidak berubah mengikut jenis senarai itu.

Ini menyokong objek dengan mudah jika bentuknya berubah atau menjadi bersarang. Medan SiftQueryInput. adalah jenis String kerana anda boleh mengakses sifat bersarang pada objek dengan sintaks titik.

Cth., menapis dengan memasukkan pertanyaan Ayak ini mungkin: { medan: 'author.name.last', penapis: JSON.stringify({ $eq: "Orwell" }) }

Kelemahan dan Kaveat

Sudah tentu, ini menggunakan rentetan untuk menyatakan bahasa pertanyaan Ayak, yang terdedah kepada ralat—jadi pengesahan yang teliti dan pengendalian ralat diperlukan untuk menggunakan pendekatan ini.

Dengan menggunakan jenis SiftQueryInput generik untuk mengumpulkan penapis pengguna, anda kehilangan jenis keselamatan GraphQL—ia tidak mempunyai cara untuk mengesahkan bahawa medan itu wujud atau sedang digunakan dengan cara yang betul di sini oleh penapis anda.

Data senarai perlu diselesaikan sepenuhnya pada titik penyelesai penapisan dijalankan. Ia tidak boleh mengakses medan lebih jauh ke bawah pertanyaan yang masih belum diselesaikan. Tetapi untuk situasi di mana data tidak datang daripada DB dengan pertanyaannya sendiri, mungkin daripada fail JSON atau respons API REST, ini mungkin juga.

Penambahbaikan Masa Depan

Saya rasa kehilangan keselamatan GraphQL adalah memalukan dalam kes ini. Anda mungkin boleh menyusun pilihan Sift Query ke dalam skema GraphQL pada masa binaan, jadi sintaks mencerminkan keadaan sebenar Sift dengan lebih serupa, tanpa bergantung pada rentetan.

Kesimpulan

Kesimpulannya, menggunakan Sift.js dalam GraphQL menyediakan cara yang fleksibel dan berkuasa untuk melaksanakan penapisan sewenang-wenangnya. Ia membawa faedah pertanyaan automatik yang biasanya dikhaskan untuk ORM dan vendor GraphQL tertentu kepada objek JavaScript biasa dalam senarai, tanpa mengira sumbernya.

Dengan menyediakan 'enjin' penapisan generik dalam pelayan GraphQL, dengan bahasa pertanyaan fleksibel yang boleh digunakan untuk sebarang jenis, logik penapisan dialihkan kepada klien GraphQL. Ini membolehkan lelaran yang lebih pantas pada penapis dan membolehkan tahap ekspresi yang lebih besar dalam penapis.

Saya ingin mendengar pendapat dan pengalaman anda dengan melaksanakan penapisan dalam GraphQL—kongsinya dalam ulasan di bawah!

Atas ialah kandungan terperinci GraphQL: Cara Mendayakan Penapisan Senarai Arbitrari dengan Sift.js.. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!