Does anyone know how I can do a common "OR" like in a where clause, in firebase?
I need to do that in the query, because I am sending the query to an adapter. So, i mean, I cannot add a listener and check one value and then another. I need to have the complete query pointing to that result in my query.
What I have is something like:
chat1:
user1Id: "1"
user2Id: "2"
bothUsers: "1_2"
chat2:
user1Id: "2"
user2Id: "4"
bothUsers: "2_4"
I need to get all the chats of the user whose id is "2". I am trying to do a query like:
userLogged = 2;
Query queryRef = firebase.orderByChild("user2Id").equalTo(userLogged);
However it will only get the chats when the user 2 is in the user2Id position. But in the example above, when the user 2 is in the user1Id (chat2) it won't get. And I need to get it. How can I do this?
In a NoSQL database you will often have to model your data for the way your app needs it (see this article for a good explanation on NoSQL Data Modeling). So if you need a list of all chats for a specific user, store that list:
/userChats
user1Id
chat1: true
user2Id
chat1: true
chat2: true
user4Id
chat2: true
This process is called denormalizing and it is covered in the article I linked above, in the Firebase documentation on structuring data and in this blog post.
Related
I am developing a car rental android application in Android Studio. I am working on a "Filter" option, so the users can filter available cars (for example they can choose to see only diesel cars with 5 seats or they can choose to see only all-wheel-drive cars, etc.). I have an activity called FilterCars where the user for example can filter by 4 components: fuel, traction, seats, gearbox. After they submit the filter, the cars are shown based on their preference. I pass those filters to Cars activity(where the cars are shown in a RecyclerView) with bundle extras with success, so I have in Cars.java stored with success user's filter in variables "fuelType, tractionType, seatsType, gearboxType".
With those filters I can pass to the recyclerview adapter a query like:
FirebaseFirestore.getInstance().collection("Cars").whereEqualTo("fuel", fuelType).whereEqualTo("traction", tractionType).whereEqualTo("seats", seatsType).whereEqualTo("gearbox", gearboxType)
which is working just fine.
My problem is the following: I don't want to force the users to complete all the filter fields, so for example, if they want to filter only by fuel and seats, they can do it. How can I make a compound query which only contains the filters chosen by the user? One way I thought about it but I can't resolve it is if, for example, the user doesn't want to filter by traction, to store in tractionType something like " " (empty), and in the compound query instead of tractionType query "whereEqualTo" to put something which returns all the cars, so the compound query will filter only by the chosen filters.
Any suggestion on how to do it? Or is there a better way in which I can avoid putting the empty answers in the compound query?
Thank you!
The following query:
FirebaseFirestore.getInstance().collection("Cars")
.whereEqualTo("fuel", fuelType)
.whereEqualTo("traction", tractionType)
.whereEqualTo("seats", seatsType)
.whereEqualTo("gearbox", gearboxType);
Will filter your collection "Cars" by the value of four properties.
I don't want to force the users to complete all the filter fields, so for example if they want to filter only by fuel and seats
There are two ways in which you can solve this issue. Taking as an example, the above query, you can remove the calls to ".whereEqualTo("traction", tractionType)" and ".whereEqualTo("gearbox", gearboxType)" and you'll have the desired result. Or, you can do as following, as it makes more sense in my opinion.
When the user opens the app for the first time, simply display all available cars that exist within your "Cars" collection:
Query query = FirebaseFirestore.getInstance().collection("Cars")
If there are too many, add a limit() call, or implement pagination. Then simply add the possibility to select the car filters. For example, add 4 check-boxes for each filtering option. Once an option is selected, add it to your Query object like so:
query = query.whereEqualTo("fuel", fuelType)
If the user selects all options, then the query will look like the first one.
Please also remember, that Firestore queries are immutable. For more info, please check my answer from the following post:
FireStore date query not working as expected
If are using for example Firebase-UI library for Android, don't forget to start/stop listening after you set a new Query. If you aren't using the library, don't forget to notify the adapter about the changes.
I am storing some data in firestore and it looks as follows:
What I have is a collection called Items, inside of it I have many documents that each has its own ID and inside each document there are multiple fields.
One of the fields is UserID which shows which user holds the item.
Now, I had like to query firestore in a way that will return me all of the items where their popularity is greater than 3.5 and when my own ID is not one of the ID's shown in the UserID array.
Is there any option to do so?
Currently im using the following:
db.collection( "Items" ).orderBy( "Popularity", Query.Direction.DESCENDING ).whereGreaterThan( "Popularity", "3.5" ).limit( 50).get()
But it also returns results where my ID appears in the array.
Firestore does not offer any queries that check for the non-existence of data in the document. Firestore indexes only work based on the presence of data - you can't efficiently index things that don't exist. So, the part of your requirements that says "when my own ID is not one of the ID's shown in the UserID array" is not possible. You can instead write code in the client app to filter out the documents where the current user's UID is missing.
Trying to fetch related data from firebase
I am new in Android and I am stuck here, want to retrieve data from Firebase where "del_id = 1" and "date = 2019-3-18" but I don't know how to write as Firebase way to retrieve what I want, Image above will further demonstrate what I have tried and what I want.
Your answer will be highly valuable for me.
The following line of code:
invSnapsjot.getValue(Invoice.class)
Returns an object of type Invoice and not a DataSnapshot object so you can call .child() method on it.
If you want to get a specific element (del_id = 1), you should simply use a query that looks like this:
myDatabase.orderByChild("del_id").equalTo("1").addValueEventListener(/* ... */);
Unfortunately, Firebase realtime database does not support queries on multiple properties but there is still a workaround for that, so please see my answer from the following post:
How to sort Firebase records by two fields (Android)
If you want to write or update value at that time you need to take .addValueEventListener
If you want to only set your value in firebase you directly set value without using .addValueEventListener
More details refer this link
https://firebase.google.com/docs/database/android/read-and-write
Is it possible to order my ListView of posts based on the likes (the most liked post must be displayed above)?
I already know how I can order it based on timestamp. But as you can see the likes is a collection in Posts.
Timestamp code:
Query firstQuery = firebaseFirestore.collection("Posts").orderBy("timestamp", Query.Direction.DESCENDING).limit(3);
If you already know how to order based on timestamp, then you should do in the same way to order by likes. So to solve this, you need to add a new property under each post named likes and use the following line of code to query:
Query firstQuery = firebaseFirestore.collection("Posts").orderBy("likes", Query.Direction.DESCENDING).limit(3);
To update a the likes property, I recomment you using Firestore Transactions.
You can count the number of documents within a collection but in your case, the best option is to add a new property, as explained above.
I have a Firebase Realtime Database with a set of Items who related to locations on a Googlemap. So every child in the Firebase have a data structure like this.
-item
latitude:"5511231165654"
longitude:"516891812013216"
postalcode: "10013"
cityname: "New York"
In my app every item from the database, where added to the related location on the Googlemap in form of a marker.
Now i think it is not a good idea to send all Items to all users. It´s more efficiently to send the user´s only these items that are relevant for them. These items are that one who are in the same area with the user, in this case same area means same postal code.
To handle this i build this Query
Query sortedByLocation = myRef.orderByChild("postalcode").equalTo(currentpostalcode);
sortedByLocation.addListenerForSingleValueEvent(
new ValueEventListener() {
.
. do something
.
}
i got the currentpostalcode from a Geocoder also the cityname. Now the problem is sometimes the Geocoder can´t decode the postal code and return null for it, but it allways return a cityname. So i changed the query to
Query sortedByLocation = myRef.orderByChild("cityname").equalTo(currentcity);
So how can i combine these two querys ? I want to do something like this:
is postalcode == null than check for cityname
The other Question will be, it is possible to retrieve data manually at need ?
Imagine the user start the app, the app now get all items who are in the same area with the user, but now the user left this area and go into a other area.
How can i trigger to retrieve the new data for this new area without to restart the app ?
Firebase Queries can only contain a single sort/filter condition.
Sometimes you can combine multiple values into a single property to get the behavior you want. For an example of that, see my answer here: Query based on multiple where clauses in firebase
But in general it sounds like you might be better off using GeoFire, which uses GeoHashes (a way of combining longitude and latitude into a single property) to allow filtering items based on their distance to a point. Note that at this moment, the updated version of GeoFire for Java is still in the works.