Android Firestore, Query Array - android

I want to query the highlighted values from the above database
My code is incomplete I can't figure how to complete the query.
I want to know if 123,456,789 exists anywhere in the entire collection,
like for a normal query .whereEqualTo("address","P18/A CIT Road Ananda Palit"); would give me the third document,here I want to query card
CollectionReference ref = db.collection("company");
Query query = ref.whereEqualTo("card[]","???");

To solve this, please use the following code:
ref.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
for (DocumentSnapshot document : task.getResult()) {
List<String> list = (List<String>) document.get("card");
for (String item : list) {
Log.d("TAG", item);
}
}
}
});
The output will be:
123
456
789
//and so on
Remember, document.get("card") does not return an array, it returns an ArraList.
If you want use a Query using whereEqualTo() method then I suggest you change your database a little bit. Your database structure shoould look like this:
Firestore-root
|
--- company
|
--- companyDocumentId
|
--- address: "P18/A CIT Road Palit"
|
--- card
|
--- 123: true
|
--- 456: true
|
--- 789: true
In this case the your query should look like this:
Query = ref.whereEqualTo("card.123", true);
Edit:
According to your commend the query should be:
Query = ref.whereEqualTo("card.E20040806709002620760CE82", true);
Edit 13 Aug 2018:
According to the updated documentation regarding array membership, now it is possible to filter data based on array values using whereArrayContains() method. A simple example would be:
CollectionReference citiesRef = db.collection("cities");
citiesRef.whereArrayContains("regions", "west_coast");
This query returns every city document where the regions field is an array that contains west_coast. If the array has multiple instances of the value you query on, the document is included in the results only once.

Related

Android Studio: Query documents containing array node using a substring

I am trying to search Documents in a Collection which contain a certain key.
Here is how I structured my Firestore database:
-- FirestoreRoot
|-- Products (Collection)
|-- Departments (Document)
|-- Food (Colletion)
|-- {Id} (Document)
-- description : "this is my very first description"
-- keywords :
-- 0 : this
-- 1 : is
-- 2 : my
-- 3 : very
-- 4 : first
-- 5 : description
In the example below, I was able to search by using a substring for the first word in the description. To this date, this method does not work for querying the following words. In the example below, typing the letters "thi" is enough to return documents.
CollectionReference colecRef = FirebaseFirestore.getInstance()
.collection("Products")
.document("Departments")
.collection("Food");
Query query = colecRef;
query.whereGreaterThanOrEqualTo("description", searchField.getText().toString().toLowerCase())
.whereLessThan("description", searchField.getText().toString().toLowerCase()+'\uf8ff')
.get().addOnSuccessListener(SearchActivity.this, new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
for (QueryDocumentSnapshot documentSnapshot : queryDocumentSnapshots) {
Log.i(TAG, "onSuccess: "+documentSnapshot);
}
}
});
In my case, I need to search by using 1 or multiple keys, for example: first or first description. And by using the whole word or only a substring, for example: first or descr
I've tried to use whereArrayContains(), but I can't use it typing multiple keys or substring.
query.whereArrayContains("keywords",searchField.getText().toString().toLowerCase())
.get().addOnSuccessListener(SearchActivity.this, new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
for (QueryDocumentSnapshot documentSnapshot : queryDocumentSnapshots) {
Log.i(TAG, "onSuccess: "+documentSnapshot);
}
}
})
I appreciate any help.
Firestore currently only offers two ways to query the contents of an array:
Array membership with whereArrayContains(). This will tell you if an element exists in an array. It must match exactly - no substrings.
array-contains-any memberhip with whereArrayContainsAny(). This will tell you if any of the given strings exist in the array. It must match exactly - no substrings.
As you can see, searching substrings in arrays isn't going to work at all. You might want to consider using another database in tandem with Firestore in order to satisfy these specific queries, as Firestore is not very well suited for them.

Firebase query on the basis of attribute exist(key)

As I am trying to short my data. So I decided to save userLikeCollection as
questionID = true/false -> where true means like and false means dislike. And if this document not exist it means it is neither like nor disliked...
and there ID comprises of (userID + questionID)
Now I want to query whether this question is like by a user. Is there a way to achieve it.
db.collection("userLikeCollection").where(questionID ).exist()
or
read that document which has property string name questionID
db.collection("userLikeCollection").whereStringProperty(questionID).exist()
where userLikeDocument look like below
(userID + questionID) -> Document Unique ID
- questionID = true/false //where questionID = any unique id for each document.
Edit Question
UserLikeDocument - 1
blahblahQuestionIdOne = true;
UserLikeDocument - 2
blahblahQuestionIdTwo = true;
UserLikeDocument - 3
blahblahQuestionIdThree = true;
UserLikeDocument - 4
blahblahQuestionIdFour = true;
Now I want to query whether this question is like by a user. Is there a way to achieve it.
db.collection("userLikeCollection").where(questionID ).exist()
Yes there is. To solve this, you should use a query and a get() call. In code it looks like this:
Query query = db.collection("userLikeCollection").whereEqualTo("questionID", true);
query.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
if (document.exists()) {
Boolean questionID = document.getBoolean("questionID");
}
}
}
}
});
In this code, the query will help you find all documents in which the questionID property will hold the value of true and the use of document.exists() will help find if that document actually exists.
or read that document which has property string name questionID
db.collection("userLikeCollection").whereStringProperty(questionID).exist()
In this case you should also use a query but instead of passing a boolean value to the whereEqualTo() method, you should pass a literal String:
Query query = db.collection("userLikeCollection").whereEqualTo("questionID", id);
In which the id holds a value of type String which is the actual id of the question that you are looking for.
(userID + questionID) -> Document Unique ID - questionID = true/false //where questionID = any unique id for each document.
This is actually possible in Firestore but only if the name of the properties are different, let's say questionID that holds a boolean value and and a id property that holds a String value. This can be done by chaining two whereEqualTo() call like this:
Query query = db.collection("userLikeCollection")
.whereEqualTo("questionID", true)
.whereEqualTo("id", id);
Edit:
According to your comment:
whereEqualTo("questionID", true) comes only if it is liked but when it is dislike .It will not retrieved
That's correct. To solve your problem, according to the official documentation regarding Query limitations:
Cloud Firestore does not support the following types of queries:
Queries with a != clause. In this case, you should split the query into a greater-than query and a less-than query. For example,
although the query clause where("age", "!=", "30") is not supported,
you can get the same result set by combining two queries, one with
the clause where("age", "<", "30") and one with the clause
where("age", ">", 30).
So with other words, there is no != (not equal to) operator in Firestore. As they say, the option that you have is to split your query into a greater-than and a less-than query and then it will work perfectly fine.
You can also create another query that looks like this:
Query query = db.collection("userLikeCollection").whereEqualTo("questionID", false);
In this case, you get the question that have the questionID property false.
Edit2:
According to your edited question, there is no way in Firestore to filter documents based on a dynamic id. There is also no way to use wildcars. The properties should have the same name.

Firebase Cloud Firestore Query whereEqualTo for reference

I am trying to create a query which only selects documents whose reference is equal to a given reference, using Java for Android development. A document which it would match contains the reference for the path "/users/someUser". I am creating the reference like so:
DocumentReference ref = mDatabase.document("users/someUser");
I have also tried:
DocumentReference ref = mDatabase.document("/users/someUser");
Then the query:
Query query = mDatabase.collection("myCollection").whereEqualTo("refField", ref).limit(10);
However, when I run the query and check the task.isSuccessful() in the onComplete method, it's not passing, i.e. it didn't work, whereas when I remove the .whereEqualTo(), it passes and the task's result isn't empty. How can I properly use .whereEqualTo() to check for all documents containing a specific reference?
An example of a document that should match my query would be:
/myCollection/GDpojS5koac2C7YlIqxS which contains the field:
refField: /users/someUser (value of type reference)
And an example of a document that should not match my query would be:
/myCollection/J5ZcVAMYU1nI5XZmh6Bv which contains the field:
refField: /users/wrongUser (value of type reference)
I think you need to add a get() method to run the query and add an onCompletionListener.
Something like this should work:
mDatabase.collection("myCollection")
.whereEqualTo("refField", ref)
.limit(10)
.get()
.addOnCompleteListener({task ->
if(task.isSuccessful){
val result = task.result
})
The above example is in kotlin, but i guess in java it is something similar
You need not to worry about the documents, if you create a query based on your fields then all the documents will be returned in the "QuerySnapshot" object,
for eg,
CollectionReference collectionReference = db.collection(FIRESTORE_USERS);
DocumentReference documentReference = collectionReference.document(userID);
CollectionReference notificationCollection = documentReference.collection(FIRESTORE_NOTIFICATIONS);
notificationCollection.whereEqualTo(USER_TYPE, userType)
.whereGreaterThanOrEqualTo(SEND_AT, calendar.getTime())
.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot documentSnapshots) {
List<DocumentSnapshot> snapshotsList = documentSnapshots.getDocuments();
ArrayList<NotificationCollections> notificationCollectionsArrayList = new ArrayList<>();
for (DocumentSnapshot snapshot : snapshotsList) {
// each document having that particular field based on query
}
}});
in the above example I am fetching all those documents which match a particular user id and also having time greater than or equal to supplied time (time will not be used in your case)
I hope this helps...
Happy coding :)

Android Firestore query get the id of the document that contains the value in the search

Firestore database image
Hello, I just tried to use Firestore. I had some problem when getting document id.
The question is, I want to get a document id (red box) which has value (blue box) in it.
I use the following query:
collection("mychannel").whereEqualTo("74wRU4xHrcV9oWAXEkKeRNp41c53")
But did not give results.
Thanks!
As in the official documentation:
Although Cloud Firestore can store arrays, it does not support querying array members or updating single array elements.
So there is no way in which you can use the following query:
collection("mychannel").whereEqualTo("74wRU4xHrcV9oWAXEkKeRNp41c53")
If you only want to get the entire userId array you need to iterate over a Map like this:
collection("mychannel").document("1fReXb8pgQvJzFdzpkSy").get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
Map<String, Object> map = document.getData();
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (entry.getKey().equals("userId")) {
Log.d("TAG", entry.getValue().toString());
}
}
}
}
}
});
But note, even if userId object is stored in the database as an array, entry.getValue() returns an ArrayList, not an array.
So the output will be:
[74wRU4xHrcV9oWAXEkKeRNp41c53]
A better approach will be if you consider this alternative database structure, where each user id is the key in a map and all values are true:
userId: {
"74wRU4xHrcV9oWAXEkKeRNp41c53": true,
"AdwF...": true,
"YsHs...": true
}
This question is answered here: Firestore: Query by item in array of document
In summary, don't use arrays to store data in Firestore as the query you are trying to do is not available yet (remember it is still in beta). You should use a Map instead.

Firebase database - Query by list of ids

I have recently started switching my app from Parse to Firebase. Everything is going great so far, but I have not been able to find a Firebase equivalent method to Parse's whereContainedIn(String key, Collection values).
This was a very useful method that allowed me to pass in an array of ids and it would return all of the rows that matched that id. So far with Firebase, I have it returning all all of the rows in the database then looping through them to see if that row's id is contained in my array of ids. The other way is to query for each id individually, which doesn't work well with Firebase's asynchronous behavior. This is what I am doing now for the first approach:
List<String> userIds = new ArrayList<>();
userIds.add("2");
userIds.add("32");
userIds.add("12545");
userIds.add("187");
DatabaseReference firebaseRef = FirebaseDatabase.getInstance().getReference();
Query queryRef = firebaseRef.child("videos");
queryRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<Video> usersVideos = new ArrayList<Video>();
for (DataSnapshot videoSnapshot : dataSnapshot.getChildren()) {
Video video = videoSnapshot.getValue(Video.class);
if (userIds.contains(video.userId)) {
usersVideos.add(video);
}
}
// usersVideos is now populated with the videos for the users
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d(TAG, "CANCELLED");
}
});
Neither of these methods seem reasonable since my table will contain hundreds of thousands of records.
Any help would be greatly appreciated!
Make another reference that can be looked up by userId and have it return all videoIds that this user has. From there you can query the videos. That means each time you save you will need to save in two spots. Sort of a pain, but it is what Firebase recommends.
So your reference will look more like:
videos -
| - <videoId> -
| - <video stuffs>
| - userId
videosByUser -
| - <userId> -
| 0 - <videoIdA>
| 1 - <videoIdB>
| - <userId2> -
| 0 - <videoIdA>
can't you just perhaps do a for loop over your ids and inside the for loop write a valueventlistener that will be called for each iterated item`?

Categories

Resources