Unable to retrieve data using whereLessThan() and whereGreaterThan() in Firestore Query - java

I want to retrieve the data from Firestore using a query that consists of whereLessThan() and whereGreaterThan() methids. But when I use the following query it returns me empty snapshot:
Query query = firestore.collection("Users").whereLessThan("id",id).whereGreaterThan("id", id).orderBy("id");
But when I use only 1 clause it successfully retrives data:
Query query = firestore.collection("Users").whereLessThan("id",id); //Working Fine
I have also tried by attaching snapshotListener to query:
query.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent( QuerySnapshot queryDocumentSnapshots, FirebaseFirestoreException e)
{
if(queryDocumentSnapshots.isEmpty()){
Toast.makeText(RetrieveUserActivity.this, "No data found", Toast.LENGTH_SHORT).show();
}
}
});
This shows Toast of No Data Found.
Here is my database structure:

If I understand it right, you are trying to exclude a single user with a specific id from your Users collection. If so, you should change the logic of your code because unfortunately, you cannot achieved this in the way you do. That's why you get an empty snapshot. If you would have been using the following line of code:
Query query = firestore.collection("Users")
.whereLessThanOrEqualTo("id",id)
.whereGreaterThanOrEqualTo("id", id)
.orderBy("id");
The snapshot object will contain only a single result, which is a single user with that particular id. The above line of code, could also be written in more simpler way like this:
Query query = firestore.collection("Users")
.whereEqualTo("id",id)
.orderBy("id");
I gave you this examples to understand better how this methods work. 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. The only 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

Related

How do I query a user's info in Firestore if all my document IDs are auto-generated?

All of the examples I'm finding online have very simple document IDs, but what do you do if you're auto-generating all your IDs (as the docs say you should)? For example, I want to query the date when the user was created. The document ID for this is below, but I've just copy-pasted it from the Firestore console. How would I know the document ID so that I may query any user's info? Note that I will be have a users, groups, usergroups, etc... There will be quite a few collections, each using the auto-ID feature. I would need to be able to update any row in any collection.
val docRef = db.collection("users").document("9AjpkmJdAdFScZaeo8FV45DT54E")
docRef.get()
.addOnSuccessListener { document ->
if (document != null) {
Log.e("Query", "Data: ${document.data}")
} else {
Log.e("Query", "Document is null")
}
}
.addOnFailureListener { exception ->
Log.e("Query", "Failure")
}
If you have data to query, that should all be stored as fields in the documents. Don't put that data in the ID of the documents - use field values.
You can filter documents in a collection using "where" clauses as shown in the documentation. What you're showing here isn't enough to go with in to make specific recommendations. But you definitely want to think about your queries ahead of time, and model your data to suit those queries.
If you need to update a document, you must first query for it, then update what you find from the query. This is extremely common, as Firestore does no provide any SQL-like "update where" queries that both locate and update data in the same command.

How make complex query with FirestoreRecyclerAdapter?

I'm developing an Android app and I need to make a complex query on my Firestore database and create a FirestoreRecyclerAdapter. To create the adpater I need a FirestoreRecyclerOptions object that take in input the whole query. Reading the documentation, I can't use in my query the methods whereGreaterThan, whereLessThan, oderBy, etc, on different parameters. For example, how can I get users from db who have age greater than/less than AND who have weight greater than/less than?
For example the document's structure in my firestore database is:
Users --->UserID--->userName(String)
--->userAge(number)
--->userHeight(number)
--->userWeight(number)
FirebaseFirestore db;
db = FirebaseFirestore.getInstance();
RecyclerView recyclerView;
recyclerView = (RecyclerView)findViewById(R.id.recyclerViewID);
.
.
.
Query query = db.collection("Users").//the complex query that i need
FirestoreRecyclerOptions<User> options = new FirestoreRecyclerOptions.Builder<User>()
.setQuery(query, User.class)
.build();
adapter = new UsersAdapter(options, this);//get in input options and the context
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
Edit: A possible solution in my last comment to answer 1
There are some query limitations when it comes to Firestore:
Query limitations
Cloud Firestore does not support the following types of queries:
Queries with range filters on different fields, as described in the previous section.
So you cannot query your database on range filters using whereGreaterThan() and whereLessThan() methods on different properties and pass it to an adapter.
Edit:
A possible solution for this issue would be to filter your records client side twice. First query the database using the first property and second using the second property. Unfortunately you cannot achieve this in a single go.
Edit2:
The solution would be to query the database using the first query, get the corresponding elements, query the database again using the second query and get the corresponding elements and then merge the results client side. Now the elements from the database were filtered twice. Pass a list of that elements to an adapter and that's it. Note, when using this solution you cannot use the Firebase-UI library anymore but this how you can get your items filtered twice.

Firestore whereEqualTo, orderBy and limit(1) not working

I want to query my Workout Collection for the latest workout from a routine. Meaning I query with whereEqualTo my routineKey, order it by the Started TimeStamp in descending order and then limit to 1 and then take the this 1st Key/Id of the Workout.
However this does not work. whereEqualTo and orderBy work separately but not combined. What am I doing wrong?
fm.getColRefWorkout().whereEqualTo("routineKey", routineKey).orderBy("startTimeStamp", Query.Direction.DESCENDING).limit(1).get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot documentSnapshots) {
workoutKey = documentSnapshots.getDocuments().get(0).getId();
//To stuff with this workoutKey
}
});
This query will not work unless you create an index for it. This can be done, by creating it manually in your Firebase Console or if you are using Android Studio, you'll find in your logcat a message that sounds like this:
FAILED_PRECONDITION: The query requires an index. You can create it here: ...
You can simply click on that link or copy and paste the URL into a web browser and your index will be created automatically.

Failed to make bulk upsert using mongo

I'm trying to do upsert using mongodb driver, here is a code:
BulkWriteOperation builder = coll.initializeUnorderedBulkOperation();
DBObject toDBObject;
for (T entity : entities) {
toDBObject = morphia.toDBObject(entity);
builder.find(toDBObject).upsert().replaceOne(toDBObject);
}
BulkWriteResult result = builder.execute();
where "entity" is morphia object. When I'm running the code first time (there are no entities in the DB, so all of the queries should be insert) it works fine and I see the entities in the database with generated _id field. Second run I'm changing some fields and trying to save changed entities and then I receive the folowing error from mongo:
E11000 duplicate key error collection: statistics.counters index: _id_ dup key: { : ObjectId('56adfbf43d801b870e63be29') }
what I forgot to configure in my example?
I don't know the structure of dbObject, but that bulk Upsert needs a valid query in order to work.
Let's say, for example, that you have a unique (_id) property called "id". A valid query would look like:
builder.find({id: toDBObject.id}).upsert().replaceOne(toDBObject);
This way, the engine can (a) find an object to update and then (b) update it (or, insert if the object wasn't found). Of course, you need the Java syntax for find, but same rule applies: make sure your .find will find something, then do an update.
I believe (just a guess) that the way it's written now will find "all" docs and try to update the first one ... but the behavior you are describing suggests it's finding "no doc" and attempting an insert.

case statement in order by clause is not working in HQL

When i am using case statement in Hibernate Query with setMaxResults() and setFirstResult() it is showing wrong records. For example, my query is
select code, text
from dropDownTable
where (code like '%meter%' or text like '%meter%')
order by case
when text like 'meter%' or code like 'meter%' then 0
when text like '%meter' or code like '%meter' then 2 else 1
end
Now I am using setMaxResults(fetchSize) and setFirstResult(fetchSize*fetchCount) in Hibernate Query. It is showing same records when fetchCount is more than 1.
I am not getting point that when we are setting start index then why it is showing records which are before that index. Please help me out in this. Following is my java code:
Query managerQuery = session.createSQLQuery(dynamicQuery);
managerQuery.setMaxResults(fetchSize);
managerQuery.setFirstResult(fetchSize * fetchCount);
returnList = managerQuery.setResultTransformer(insensitiveAliasTransformer).list();

Categories

Resources