Penelusuran Teks Lengkap

Sebagian besar aplikasi memungkinkan pengguna untuk menelusuri konten aplikasi. Misalnya, Anda mungkin ingin menelusuri postingan yang berisi kata atau catatan tertentu yang telah Anda tulis tentang topik tertentu.

Cloud Firestore tidak mendukung pengindeksan asli atau pencarian kolom teks dalam dokumen. Selain itu, mengunduh keseluruhan koleksi untuk menelusuri kolom di sisi klien itu tidak praktis.

Solusi: Algolia

Untuk mengaktifkan penelusuran teks lengkap dari data Cloud Firestore, gunakan layanan penelusuran pihak ketiga, seperti Algolia. Pertimbangkan aplikasi penulisan catatan yang akan menganggap setiap catatan sebagai dokumen:

// /notes/${ID}
{
  owner: "{UID}", // Firebase Authentication's User ID of note owner
  text: "This is my first note!"
}

Anda dapat menggunakan Algolia dengan Cloud Functions untuk mengisi indeks dengan konten dari setiap catatan dan mengaktifkan penelusuran. Pertama-tama, konfigurasikan klien Algolia menggunakan ID Aplikasi dan kunci API Anda:

Node.js

// Initialize Algolia, requires installing Algolia dependencies:
// https://www.algolia.com/doc/api-client/javascript/getting-started/#install
//
// App ID and API Key are stored in functions config variables
const ALGOLIA_ID = functions.config().algolia.app_id;
const ALGOLIA_ADMIN_KEY = functions.config().algolia.api_key;
const ALGOLIA_SEARCH_KEY = functions.config().algolia.search_key;

const ALGOLIA_INDEX_NAME = 'notes';
const client = algoliasearch(ALGOLIA_ID, ALGOLIA_ADMIN_KEY);

Selanjutnya, tambahkan fungsi yang akan mengupdate indeks setiap kali catatan ditulis:

Node.js

// Update the search index every time a blog post is written.
exports.onNoteCreated = functions.firestore.document('notes/{noteId}').onCreate((snap, context) => {
  // Get the note document
  const note = snap.data();

  // Add an 'objectID' field which Algolia requires
  note.objectID = context.params.noteId;

  // Write to the algolia index
  const index = client.initIndex(ALGOLIA_INDEX_NAME);
  return index.saveObject(note);
});

Setelah data Anda diindekskan, Anda dapat menggunakan integrasi Algolia di iOS, Android, atau Web untuk melakukan penelusuran melalui data.

Web

var client = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_SEARCH_KEY);
var index = client.initIndex('notes');

// Perform an Algolia search:
// https://www.algolia.com/doc/api-reference/api-methods/search/
index
  .seach({
    query
  })
  .then(function(responses) {
    // Response from Algolia:
    // https://www.algolia.com/doc/api-reference/api-methods/search/#response-format
    console.log(responses.hits);
  });

Menambahkan Keamanan

Solusi asli bekerja dengan baik jika semua catatan dapat ditelusuri oleh semua pengguna. Namun, banyak kasus penggunaan memerlukan pembatasan hasil yang aman. Untuk kasus penggunaan ini, Anda dapat menambahkan Cloud Function HTTP yang menghasilkan Kunci API Aman yang menambahkan filter khusus ke setiap kueri yang dilakukan oleh pengguna.

Node.js

// This complex HTTP function will be created as an ExpressJS app:
// https://expressjs.com/en/4x/api.html
const app = require('express')();

// We'll enable CORS support to allow the function to be invoked
// from our app client-side.
app.use(require('cors')({origin: true}));

// Then we'll also use a special 'getFirebaseUser' middleware which
// verifies the Authorization header and adds a `user` field to the
// incoming request:
// https://gist.github.com/abehaskins/832d6f8665454d0cd99ef08c229afb42
app.use(getFirebaseUser);

// Add a route handler to the app to generate the secured key
app.get('/', (req, res) => {
  // Create the params object as described in the Algolia documentation:
  // https://www.algolia.com/doc/guides/security/api-keys/#generating-api-keys
  const params = {
    // This filter ensures that only documents where author == user_id will be readable
    filters: `author:${req.user.user_id}`,
    // We also proxy the user_id as a unique token for this key.
    userToken: req.user.user_id,
  };

  // Call the Algolia API to generate a unique key based on our search key
  const key = client.generateSecuredApiKey(ALGOLIA_SEARCH_KEY, params);

  // Then return this key as {key: '...key'}
  res.json({key});
});

// Finally, pass our ExpressJS app to Cloud Functions as a function
// called 'getSearchKey';
exports.getSearchKey = functions.https.onRequest(app);

Jika Anda menggunakan fungsi ini untuk menyediakan kunci penelusuran Algolia, pengguna hanya dapat menelusuri catatan yang kolom author-nya sama persis dengan ID penggunanya.

Web

// Use Firebase Authentication to request the underlying token
return firebase.auth().currentUser.getIdToken()
  .then(function(token) {
    // The token is then passed to our getSearchKey Cloud Function
    return fetch('https://us-central1-' + PROJECT_ID + '.cloudfunctions.net/getSearchKey/', {
        headers: { Authorization: 'Bearer ' + token }
    });
  })
  .then(function(response) {
    // The Fetch API returns a stream, which we convert into a JSON object.
    return response.json();
  })
  .then(function(data) {
    // Data will contain the restricted key in the `key` field.
    client = algoliasearch(ALGOLIA_APP_ID, data.key);
    index = client.initIndex('notes');

    // Perform the search as usual.
    return index.search({query});
  })
  .then(function(responses) {
    // Finally, use the search 'hits' returned from Algolia.
    return responses.hits;
  });

Mengambil kunci penelusuran untuk setiap kueri tidaklah diperlukan. Anda harus menyimpan kunci yang diambil atau klien Algolia ke dalam cache, guna mempercepat penelusuran.

Pembatasan

Solusi yang ditunjukkan di atas adalah cara mudah untuk menambahkan penelusuran teks lengkap ke data Cloud Firestore Anda. Namun, perhatikan bahwa Algolia bukan satu-satunya penyedia penelusuran pihak ketiga. Pertimbangkan alternatif lain, seperti ElasticSearch sebelum menerapkan solusi apa pun ke produksi.

Kirim masukan tentang...

Butuh bantuan? Kunjungi halaman dukungan kami.