Based on the fact that Cloud Firestore does not support Full-Text Search to date, I decided to ask this question some time ago. Inspired by this write-up by Alex Mamo I was able to simulate a full-text search scenario on Cloud Firestore by implementation the following from the write-up.
ProductRepository class's getProductNameListMutableLiveData() method fetches all the productNames at once
class ProductRepository {
private FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
private DocumentReference productSearchRef = rootRef.collection("data").document("productSearch");
private CollectionReference productsRef = rootRef.collection("SearchList");
MutableLiveData<List<String>> getProductNameListMutableLiveData() {
MutableLiveData<List<String>> productNameListMutableLiveData = new MutableLiveData<>();
productSearchRef.get().addOnCompleteListener(productNameListTask -> {
if (productNameListTask.isSuccessful()) {
DocumentSnapshot document = productNameListTask.getResult();
if (document.exists()) {
List<String> productNameList = (List<String>) document.get("productNames");
productNameListMutableLiveData.setValue(productNameList);
}
} else {
Log.d("Name List Error: ", productNameListTask.getException().getMessage());
}
});
return productNameListMutableLiveData;
}
MutableLiveData<String> getProductPriceMutableLiveData(String productName) {
MutableLiveData<String> productPriceMutableLiveData = new MutableLiveData<>();
productsRef.whereEqualTo("prodName", productName).get().addOnCompleteListener(productTask -> {
if (productTask.isSuccessful()) {
if (productTask.isSuccessful()) {
for (QueryDocumentSnapshot document : productTask.getResult()) {
productPriceMutableLiveData.setValue(document.toObject(Product.class).itemLink);
}
}
} else {
Log.d("Item Link Error: ", productTask.getException().getMessage());
}
});
return productPriceMutableLiveData;
}
}
Now my question is:
- How can we improvise/decrease the
READ-COUNTon the Cloud Firestore by searching by the first alphabet, which may optimize the case over a large dataset. - How can we get data orderly from something like this, so that whenever the data is passed on to the following it only reads the requisite first alphabet
private void getProductNameList() {
productViewModel.getProductNameListLiveData().observe(this, productNameList -> {
productNamesAdapter = new ProductNamesAdapter(this, productNameList);
Log.d("ProductName List---", "getProductNameList: " + productNameList);
autoComplete.setAdapter(productNamesAdapter);
});
}
This is the Filter method which allows implementing the Filter/Search logic
private Filter productNameFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
List<String> suggestionList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
suggestionList.addAll(productNameListFull);
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (String productName : productNameListFull) {
if (productName.toLowerCase().contains(filterPattern)) {
suggestionList.add(productName);
}
}
}
results.values = suggestionList;
results.count = suggestionList.size();
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
List<String> productNameList = (List<String>) results.values;
if (productNameList != null) {
clear();
addAll(productNameList);
}
notifyDataSetChanged();
}
@Override
public CharSequence convertResultToString(Object resultValue) {
return (String) resultValue;
}
};
You can find the full code here