Skip to content

Commit 1e2da38

Browse files
authored
Add Elastic FTS option (#877)
1 parent 9ba6e91 commit 1e2da38

File tree

4 files changed

+102
-3
lines changed

4 files changed

+102
-3
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,9 @@ Uses a Realtime Database trigger.
188188
Integrates the Bit.ly API to shorten URLs automatically as they are added to the database.
189189
Uses a Realtime Database trigger.
190190

191-
### Full-text search via Algolia for [Realtime Database](/fulltext-search) or [Firestore](/fulltext-search-firestore)
191+
### Full-text search for [Realtime Database](/fulltext-search) or [Firestore](/fulltext-search-firestore)
192192

193-
Enable full-text search on Firebase Database data or Firestore documents by using an Algolia hosted search service.
193+
Enable full-text search on Firebase Database data or Firestore documents by using a hosted search service.
194194
Uses a Realtime Database or Firestore trigger.
195195

196196
### [User data cleanup](/user-data-cleanup)
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/**
2+
* Copyright 2021 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the 'License');
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an 'AS IS' BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
const functions = require("firebase-functions");
17+
18+
// [START init_elastic]
19+
const { Client } = require("@elastic/elasticsearch");
20+
21+
// Initialize Elastic, requires installing Elastic dependencies:
22+
// https://github.com/elastic/elasticsearch-js
23+
//
24+
// ID, username, and password are stored in functions config variables
25+
const ELASTIC_ID = functions.config().elastic.id;
26+
const ELASTIC_USERNAME = functions.config().elastic.username;
27+
const ELASTIC_PASSWORD = functions.config().elastic.password;
28+
29+
const client = new Client({
30+
cloud: {
31+
id: ELASTIC_ID,
32+
username: ELASTIC_USERNAME,
33+
password: ELASTIC_PASSWORD,
34+
}
35+
});
36+
// [END init_elastic]
37+
38+
// [START update_index_function_elastic]
39+
// Update the search index every time a blog post is written.
40+
exports.onNoteCreated = functions.firestore.document('notes/{noteId}').onCreate(async (snap, context) => {
41+
// Get the note document
42+
const note = snap.data();
43+
44+
// Use the 'nodeId' path segment as the identifier for Elastic
45+
const id = context.params.noteId;
46+
47+
// Write to the Elastic index
48+
client.index({
49+
index: "notes",
50+
id,
51+
body: note,
52+
});
53+
});
54+
// [END update_index_function_elastic]
55+
56+
// [START search_function_elastic]
57+
exports.searchNotes = functions.https.onCall(async (data, context) => {
58+
const query = data.query;
59+
60+
// Search for any notes where the text field contains the query text.
61+
// For more search examples see:
62+
// https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/search_examples.html
63+
const searchRes = await client.search({
64+
index: "notes",
65+
body: {
66+
query: {
67+
query_string: {
68+
query: `*${query}*`,
69+
fields: [
70+
"text"
71+
]
72+
}
73+
}
74+
}
75+
});
76+
77+
// Each entry will have the following properties:
78+
// _score: a score for how well the item matches the search
79+
// _source: the original item data
80+
const hits = searchRes.body.hits.hits;
81+
82+
const notes = hits.map(h => h["_source"]);
83+
return {
84+
notes: notes
85+
};
86+
});
87+
// [END search_function_elastic]

fulltext-search-firestore/functions/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"name": "full-text-search",
33
"description": "Full text search for Firestore",
44
"dependencies": {
5+
"@elastic/elasticsearch": "^7.13.0",
56
"algoliasearch": "^4.0.3",
67
"cors": "^2.8.5",
78
"express": "^4.17.1",

fulltext-search-firestore/public/index.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ function unauthenticated_search(query) {
2626

2727
// Perform an Algolia search:
2828
// https://www.algolia.com/doc/api-reference/api-methods/search/
29-
return index
29+
return index
3030
.search({
3131
query
3232
})
@@ -90,6 +90,17 @@ function search(query) {
9090
}
9191
}
9292

93+
function searchElastic(query) {
94+
// [START search_elastic]
95+
const searchNotes = firebase.functions().httpsCallable('searchNotes');
96+
searchNotes({ query: query })
97+
.then((result) => {
98+
const notes = result.data.notes;
99+
// ...
100+
});
101+
// [END search_elastic]
102+
}
103+
93104
// Other code to wire up the buttons and textboxes.
94105

95106
document.querySelector('#do-add-note').addEventListener('click', function() {

0 commit comments

Comments
 (0)