Firestore order a collection based on likes - java

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.

Related

Android Firestore compound query

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.

Firestore: Query names that match or similar to the searched term

I have a list of users with their names in the Firestore database. What I am trying to achieve is to make users able to search and find other users. My problem is that:
Query query = db.collection("users").whereEqualTo("name", searchTerm);
FirestoreRecyclerOptions<UserObject> response = new FirestoreRecyclerOptions.Builder<UserObject>()
.setQuery(query, UserObject.class)
.build();
In the code above, I am able to find users only if I write their first and last name exactly right. But what I want is to get users that do have similar names or last names. And also, users' last and first names are stored in one string variable. Like in facebook, if you search some names, it will display the similar names as well. Is there a good way to achieve that with firestore?
As per official documentation:
Cloud Firestore doesn't support native indexing or search for text fields in documents. Additionally, downloading an entire collection to search for fields client-side isn't practical.
So I strongly recommend you not to download the entire collection in order to create a search, isn't worth it. But in order to have a slightly better search, I recommend you use the following query:
Query query = db.collection("users").startAt(searchText).endAt(searchText+ "\uf8ff");
If this query isn't what you are searching for, I recommend you use Algolia search, which is also recommended by Firebase. I also recommend you see this video.
Late answer but for anyone who's still looking for an answer try this.
Query query = db.collection("users").whereGreaterThanOrEqualTo("name", searchTerm);

How to check in hibernate that same data with different id exists?

As given in the below code I am inserting data in table by simple hibernate code.
But when all the fields are then also it is saving data in table but only id is changed
(auto-incremented). I want to know is there any way to know that the same data exists in table & I can save redundant inserts. Please tell an easy way I know I can write queries anytime to figure out the same.
List<Route> listRoute = newList();
listRoute.get(0).setSource("DelhiTest");
listRoute.get(0).setDestination("KotaTest");
listRoute.get(1).setSource("DelhiTest");
listRoute.get(1).setDestination("KotaTest");
listRoute.get(2).setSource("DelhiTest");
listRoute.get(2).setDestination("KotaTest");
RowReferenceByEntity.setListRoute(listRoute);
new RouteDAOImpl().saveOnly(listRoute.get(0));
new RouteDAOImpl().saveOnly(listRoute.get(1));
new RouteDAOImpl().saveOnly(listRoute.get(2));
Thanks
Searching for duplicate rows already persisted can lead to performance issues. For each new item you ill need to search a match in that table.
To guarantee routes are unique you can create a unique index covering source and destination ids. Any attempt to duplicate data ill throw an exception. and this ill work fast.
But if all you want is to just find duplicate items in a list look at this post.
How to find duplicate items in list
This query counts how many ids have the same value:
SELECT COUNT(id), value
FROM table
GROUP BY value

Google Search API: Loading all datastore data into document builder for full text search on all records

I have been following the tutorial regarding the Google Search API at https://developers.google.com/appengine/docs/java/search/overview. The information I have found is very clear on how to build the document and load it into an index. What I am not sure of is how to load the datastore data into the document.
What am trying to achieve is a simple %LIKE% query on a few fields. For example, I am working on a music library. If the user types in "glory", then I would like to use the Search API to return all entities with "glory" somewhere in the title. I have implemented the "starts with" work around by adding the search text to "\uFFFD", however, I find this insufficient. My users will be very novice, and it would also be helpful if they didn't have to pick a field as in a traditional search. So full text search seems the solution.
Here are my questions:
Should each record in my datastore be a document? Or all the records into one document? I have a pretty well fixed datastore size of only 1000 records. Could anyone provide an example of the correct method?
I would like to return the entire datastore entity (it's only 8 fields) as an Iterable of the type of my entity. Do we specify each field we need to return? The example just says:
for (ScoredDocument scoredDocument : results) {
// process scoredDocument
}
Does anybody have an example of what comes out of the stored document? Is it exactly what we put in or must you identify each field again? Or an example of processes a ScoredDocument returning a datastore entities?
If anybody could help fill in these blanks for me, I would appreciate it.
Thank you for looking at this with me.
What am trying to achieve is a simple %LIKE% query on a few fields
In order to achieve this you need to "tokenize" your records name, GAE provides FULL TEXT SEARCH so in order for you to get partial matches you need to add partial matches for every record so:
If your record's name is "Glory" you should add the tokens for "G","Gl","Glo","Glor","y","ry","ory","lory"
Here's a very basic implementation I use to provide partial search results (only for "starts with" not implementing "end with")
public void addField(String name, String value, boolean tokenize) {
addField(Field.newBuilder().setName(name).setText(value));
if (tokenize) {
for (int i = startTokenIndex ; i < value.length() ;i++) {
addField(Field.newBuilder().setName("token" + (lastTokenIndex++))
.setText(value.substring(0, i)));
}
}
}
Should each record in my datastore be a document?
Yes. you could even match the document ID with the entity's datastore ID for quick matching. (or you can just add it as a separate field)
I would like to return the entire datastore entity (it's only 8
fields) as an Iterable of the type of my entity. Do we specify each
field we need to return?
You need to store your entity's ID in your document, that way when your search returns a set of documents you just retrieve all entities with those IDs.
Does anybody have an example of what comes out of the stored document?
Is it exactly what we put in or must you identify each field again? Or
an example of processes a ScoredDocument returning a datastore
entities?
Documents return all fields you stored in them, plus a lot of data like scoring, id, etc. The "processing" in your case would consist of getting the entity id form the Document.
If you are certain your records wont grow above 1000 you could virtually store everything within your search index. Just bear in mind the index is not designed for that and will face some serious limitations when scaling, which the datastore obviously doesn't.

Solr. Updating a document multi-value field (no dup values) without needed it to be already committed

Sorry for the lengthy text, it's a bit difficult to explain:
We are using Solr to index some user info like username, email (among other things).
I'm also trying to use facets for search, so for example, I added a multi-value field to user called "organizations" where I would store the name of the organizations that user work for.
So i can use that field for facetted search and be able to filter a user search query result by the organizations this user work for.
So now, the issue I have is my code does something like:
1) Add users documents to Solr
2) When a user is assigned an organization membership(role), update the user doc to set the organizations field
Now I have the following issue with step 2:
If I just do a addField("organizations", "BigCorp") on the user doc, it will add that value regardless if organizations already have that value("BigCorp") or not, but I want each org name to appear only once.
So only way I found to get that behavior is to query the user document, get the values of "organization" and only add the new value if it's not already in there - if !userDoc.getValues("organiations").contains(value) {... add the value to the doc and save it ...}-
Now that works well, but only if I commit all the time(between step 1 & 2 at least), because the document query will not work unless it has been committed already. Obviously in theory its best not to commit all the time performance-wise, and unpractical since I process those inserts in batches.
So I guess the main issue would be:
Is there a way to update a multi-value field, without allowing duplicates, that would not require querying the doc to manually prevent duplicates ?
Maybe some better way to do this ?
Thanks.
Couple of things -
For multiple duplicate values in the faceted field, the value in faceted field is counted just once. So even if you add multiple same values, that would be reflected as a single value in the facet count entry. Have tested this. you too can confirm.
Also, when you reindex the document why would you need to check whats in the existing document. As I presume you would have the unique list of organizations and when fed to Solr, the document would be deleted and inserted.

Categories