I have the following firestore setup:
-Root
- Queue
- item1
- time : 20
- item2
- time : 1
- 2000 more items, with a random time value
What i want is to show 40 items, with smallest time first so i do the following in kotlin:
val ref = firestore.collection("Queue")
orderBy?.let{
ref.orderBy(it)
}
limit?.let{
ref.limit(it)
}
return ref.get().get().toObjects(Queue::class.java)
It actually completly ignore my order by and limit statements. and is returning all items in the Queue collection, what am i doing wrong.
The documentation here:
https://firebase.google.com/docs/reference/android/com/google/firebase/firestore/Query
says that the orderBy and limit methods return a new query object, so maybe you should try
val ref = firestore.collection("Queue").orderBy("time").limit(40)
As per the update to your question, you could create a function that returns the query you want based on whether or not the orderBy and limit query modifiers are present. You would have to make that query object a var in order to make it mutable.
Related
I would like to make arecyclerView with pagination in my project. However, I got stuck on the process.
My firestore data is built as follows (some of the documents has visibility=false as a value so I dont want them to appear):
Now, I had like to get the first 5 documents ordered by dateCreated and then to continue pagination by the last value that I previously received.
I tried using the following:
db
.collection( "Quotes" )
.whereEqualTo( "visibility", true )
.orderBy("dateCreated", Query.Direction.DESCENDING )
.startAfter("dateCreated", dateCreatedOrig
.get(dateCreatedOrig.size()-1))
.limit(5)
.get()
.addOnCompleteListener( task -> {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
...
}
}
dAdapter = new Ddapter(...);
ddapter.notifyDataSetChanged();
rv_Quotes.setAdapter( ddapter );
}
} );
Where dateCreatedOrig is List that contains the timestamp of the first query so I get the last time stamp to continue the pagination from there.
However, I get the following error:
java.lang.IllegalArgumentException: Too many arguments provided to startAfter(). The number of arguments must be less than or equal to the number of orderBy() clauses.
Any ideas?
The problem here is that you are passing 2 arguments to startAfter. If you see the documentation for startAfter, you will see that it:
Creates and returns a new Query that starts after the provided fields relative to the order of the query. The order of the field values must match the order of the order by clauses of the query
Meaning that you define the field name that will be used in the orderBy clause, not the startAfter, and both should be used together. So in you case, all that needs to be done it removing the first argument of startAt and it will work, so it could look like this:
db.collection( "Quotes" )
.whereEqualTo( "visibility", true )
.orderBy("dateCreated", Query.Direction.DESCENDING )
.startAfter(dateCreatedOrig.get(dateCreatedOrig.size()-1))
.limit(5)
.get()
.addOnCompleteListener(...);
I'm trying to implement pagination as explained in a web tutorial but I don't understand what is the order of functions in query for maximum speed. This is my code:
Query query = db.orderBy("name", Query.Direction.ASCENDING)
.startAt("John").endAt("John" + "\uf8ff")
.startAfter(lastVisible)
.limit(10); //Called last
Or:
Query query = db.orderBy("name", Query.Direction.ASCENDING)
.limit(10) // Called first
.startAt("John").endAt("John" + "\uf8ff")
.startAfter(lastVisible);
Or:
Query query = db.orderBy("name", Query.Direction.ASCENDING)
.limit(10) // Called first
.startAfter(lastVisible)
.startAt("John").endAt("John" + "\uf8ff"); // Called last
All three compile fine, I have no error. How to make it correct for fast pagination?
From the perspective of performance, the order in which you build the Query object doesn't matter. The end result is a Query with the same internal configuration.
However, startAt is not compatible with startAfter. Only one or the other will take effect, likely the one that appears last in the builder chain.
I am trying to use the DynamoDBScanExpression withLimit of 1 using Java aws-sdk version 1.11.140
Even if I use .withLimit(1) i.e.
List<DomainObject> result = mapper.scan(new DynamoDBScanExpression().withLimit(1));
returns me list of all entries i.e. 7. Am I doing something wrong?
P.S. I tried using cli for this query and
aws dynamodb scan --table-name auditlog --limit 1 --endpoint-url http://localhost:8000
returns me just 1 result.
DynamoDBMapper.scan will return a PaginatedScanList - Paginated results are loaded on demand when the user executes an operation that requires them. Some operations, such as size(), must fetch the entire list, but results are lazily fetched page by page when possible.
Hence, The limit parameter set on DynamoDBScanExpression is the maximum number of items to be fetched per page.
So in your case, a PaginatedList is returned and when you do PaginatedList.size it attempts to load all items from Dynamodb, under the hood the items were loaded 1 per page (each page is a fetch request to DynamoDb) till it get's to the end of the PaginatedList.
Since you're only interested in the first result, a good way to get that without fetching all the 7 items from Dynamo would be :
Iterator it = mapper.scan(DomainObject.class, new DynamoDBScanExpression().withLimit(1)).iterator();
if ( it.hasNext() ) {
DomainObject dob = (DomainObject) it.next();
}
With the above code, only the first item will fetched from dynamodb.
The take away is that : The limit parameter in DynamoDBQueryExpression is used in the pagination purpose only. It's a limit on the amount of items per page not a limit on the number of pages that can be requested.
I have a collection from which I am getting max id and while inserting using max id + 1. The id column is unique in this collection.
When multiple instances of this service is invoked the concurrent application reads the same collection and gets the max id. But since the same collection is accessed the same max id is returned to multiple instances, can I get an explicit lock on the collection while reading the data from this collection and release the lock after writing in Mongo DB?
Using mongoDB method collections.findAndModify() you can create your own "get-and-increment" query.
For example:
db.collection_name.findAndModify({
query: { document_identifier: "doc_id_1" },
update: { $inc: { max_id: 1 } },
new: true //return the document AFTER it's updated
})
https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/
Take a look at this page for more help:
https://www.tutorialspoint.com/mongodb/mongodb_autoincrement_sequence.htm
Try this approach
Instead of getting the max id in read of the collection and increment it as max id + 1.
While read for multiple instances just give the document/collection, and while updating follow the below logic
Let us have the below part in a synchronized block, so that no two threads gets the same max id
synchronize() {
getMaxId from collection
increase it by 1
insert the new document
}
Please refer:
https://docs.mongodb.com/v3.0/tutorial/create-an-auto-incrementing-field/
https://www.tutorialspoint.com/mongodb/mongodb_autoincrement_sequence.htm
Hope it Helps!
I am creating a view in code using the Couchbase Java API 2.1.2 like this:
DefaultView view = DefaultView.create(viewName, jsMapFunctionAsString);
List<View> views = new ArrayList<>();
views.add(view);
DesignDocument doc = DesignDocument.create(name, views);
bucket.bucketManager().insertDesignDocument(doc);
Calling ViewResult result = bucket.query(ViewQuery.from(name, viewName)) directly after inserting the document, viewResult.success() always returns true, but both iterators rows() and iterator return 0 rows (there are definitely results present. When I execute the view in the web interface, it returns correct values).
The workaround I found after several hours is to call query twice with enough waiting time in between like
ViewResult result = bucket.query(ViewQuery.from(name, viewName));
Thread.sleep(10000);
result = bucket.query(ViewQuery.from(name, viewName));
The second call will then return the correct result.
It seems as if Couchbase has to build the index for the query first but returns directly, even before the index has been built.
Waiting 10 seconds is of course not optimal, maybe creating the index will take more time in the future.
So my question is, how can I make sure, that I only wait until the index has been built?
Is this a bug in the API?
You can use the stale method and set it to false in the ViewQuery, this will force to wait for the indexation to finish before returning results.