How to Use Algolia Query in Firestorerecycleroptions

Is it possible to use Algolia query in FirestoreRecyclerOptions?

For a better understanding, I'll try to explain this with an example. Let's assume we have a FirebaseFirestore object that points to the root reference of the database and a CollectionReference object that points to a collection named products. And for that we can use the following two lines of code:

FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference productsRef = rootRef.collection("products");

Let's aslo assume we have a Cloud Firestore database that looks like this:

Firestore-root
|
--- products
|
--- productIdOne
| |
| --- productName: "Milk"
|
--- productIdTwo
|
--- productName: "Soy Milk"
|
--- productIdThree
|
--- productName: "Bacon"

To achieve this structure, let's add these products to the database and also the corresponding indexes, using the code below:

Map<String, Object> mapOne = new HashMap<>();
mapOne.put("productName", "Milk");
Map<String, Object> mapTwo = new HashMap<>();
mapTwo.put("productName", "Soy Milk");
Map<String, Object> mapThree = new HashMap<>();
mapThree.put("productName", "Bacon");

WriteBatch writeBatch = rootRef.batch();
writeBatch.set(productsRef.document(), mapOne);
writeBatch.set(productsRef.document(), mapTwo);
writeBatch.set(productsRef.document(), mapThree);
writeBatch.commit();

Client client = new Client(YourApplicationID, YourAPIKey);
Index index = client.getIndex("products");

List<JSONObject> productList = new ArrayList<>();
productList.add(new JSONObject(mapOne));
productList.add(new JSONObject(mapTwo));
productList.add(new JSONObject(mapThree));
index.addObjectsAsync(new JSONArray(productList), null);

Let's also assume we have 2 views in out layout file, an EditText and a ListView.

EditText editText = findViewById(R.id.edit_text);
ListView listView = findViewById(R.id.list_view);

To actually display those products in our ListView, let's use the following code:

productsRef.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
List<String> list = new ArrayList<>();
for (DocumentSnapshot document : task.getResult()) {
list.add(document.getString("productName"));
}
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, list);
listView.setAdapter(arrayAdapter);
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
}
});

In order to filter the products according to the text that we type in our EditText, we need to add a TextChangedListener like this:

editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}

@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}

@Override
public void afterTextChanged(Editable editable) {
Query query = new Query(editable.toString())
.setAttributesToRetrieve("productName")
.setHitsPerPage(50);
index.searchAsync(query, new CompletionHandler() {
@Override
public void requestCompleted(JSONObject content, AlgoliaException error) {
try {
JSONArray hits = content.getJSONArray("hits");
List<String> list = new ArrayList<>();
for (int i = 0; i < hits.length(); i++) {
JSONObject jsonObject = hits.getJSONObject(i);
String productName = jsonObject.getString("productName");
list.add(productName);
}
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, list);
listView.setAdapter(arrayAdapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
});

So in order to make it work, we have created a new adapter object. This means that for every character that we type in the EditText, we create a new adapter and we populate this adapter with the results that are coming from the database. And to answer your question, in order to achieve what you want, you don't have to change the JSONObject, you have create a new query object that should be passed to the setQuery() method that is called on the FirestoreRecyclerOptions object. I just gave you a simpler example to understand the flow. For more information, I also recommend you see this video.

How to search in Firestore database?

When you are using the following call:

.where('name', isGreaterThanOrEqualTo: customer)

It means that you are searching the database for the documents in which the "name" property holds a value that is greater than the one you are typing. In this particular case, both "Omar" and "Second Omar" are present in the result-set, since each one of them starts with a letter that is alphabetically ordered after "k". In fact, all capital letters are present in alphabetical order after the lower-case letters. Remember that the search is performed lexicographically.

If you are looking for a full-text search, please note that Firestore doesn't provide one. As @Dharmaraj mentioned in his comment, you should use a third-party solution. You can also find more info in my answer from the following posts:

  • Search by pattern on Cloud Firestore collection

  • Is it possible to use Algolia query in FirestoreRecyclerOptions?

How to filter multiple fields in Firestore Android

Partial text search is not a supported feature with Firestore, it uses a direct comparison for values.

You will have to implement a custom search feature yourself by 3rd party API like Algolia with cloud functions or create a breakdown of all the text in strings that support broken down letter combinations - but this can increase reads unwantedly and I do not recommend it.

Does Firestore already support search?

Just wandering if Firestore already support full text search or does it still relay on Algolia.

No, it does not support full-text search.

Documentation form my experience is not always up to date

The official documentation regarding the full-text search in Cloud Firestore, is up to date and stands for Algolia.

For Android, please see my answer from the following question:

  • Is it possible to use Algolia query in FirestoreRecyclerOptions?

Edit:

Acording to the offical documentation regarding mobile search:

We offer front end components for iOS, Android and mobile web. Each flavor respects the specific concepts, coding patterns and UX/UI best practices of its framework, so developers can quickly build state-of-the-art, mobile search and discovery experiences.

How to search and fetch documents from cloud firestore which matches a specific string

As I understand from your comments, you want to query the database based on substrings that can exist in the id of the documents but unfortunately this is not possible. The simplest solution I can think of is to add the id of the document as a property in your item object (document). So your schema should look like this:

Firestore-root
|
--- Items (collection)
|
--- Jeera Rice (document)
|
--- imageUrl: "https://..."
|
--- price: 70
|
--- documentId: "Jeera Rice"

Even if you'll do this way, you won't be able to search by substrings. To enable full text search of your Cloud Firestore data, use a third-party search service like Algolia. To achieve this in Android, please see my answer from the following post:

  • Is it possible to use Algolia query in FirestoreRecyclerOptions?


Related Topics



Leave a reply



Submit