Using github.com/icza/minquery to directly query page 3 value - mongodb

I wanna confirm the right way to get skip(3) values using minquery, 1. foreach skip, get 1,2,3 page data, then return the 3rd value? or 2. use a way to get the cursor of skip(3). if the 2rd is right, how to get the cursor of skip(3) page? Thanks.

You can't skip documents directly using github.com/icza/minquery. The purpose of minquery is to not have to use Query.Skip() (because that becomes less efficient when the number of "skippable" documents grows). The only way to skip 3 documents is to query for more than 3, and throw away the first 3.
minquery is for cases where you don't have to skip the initial documents. minquery requires you to iterate over the documents, and acquire the cursor that encodes the index entry of the last returned document (this cursor is returned to you by MinQuery.All()). When you need the next page, you have to use the cursor you acquired in the previous query, and then it can list subsequent documents without having to skip anything, because the encoded index entry can be used to jump right where the last query finished listing documents.
Think of GMail: you can always jump just to the next (and previous) page of emails, but you have no way of "magically" jumping to the 10th or 100th page: GMail uses the same mechanism under the hood.

Related

Firestore 1 global index vs 1 index per query what is better?

I'm working on my app and I just ran into a dilemma regarding what's the best way to handle indexes for firestore.
I have a query that search for publication in a specify community that contains at least one of the tag and in a geohash range. The index for that query looks like this:
community Ascending tag Ascending location.geohash Ascending
Now if my user doesnt need to filter by tag, I run the query without the arrayContains(tag) which prompt me to create another index:
community Ascending location.geohash Ascending
My question is, is it better to create that second index or, to just use the first one and specifying all possible tags in arrayContains in the query if the user want no filters on tag ?
Neither is pertinently better, but it's a typical space vs time tradeoff.
Adding the extra tags in the query adds some overhead there, but it saves you the (storage) cost for the additional index. So you're trading some small amount of runtime performance for a small amount of space/cost savings.
One thing to check is whether the query with tags can actually run on just the second index, as Firestore may be able to do a zigzag merge join. In that case you could only keep the second, smaller index and save the runtime performance of adding additional clauses, but then get a (similarly small) performance difference on the query where you do specify one or more tags.

How to skip elements before certain document

Background:
I am writing a mobile application which has lazy loading page. My backend is using go and mongodb with mongo-go driver. There are 10 elements on that page and i want to get next ten when i scroll to the bottom. I am planning to send ObjectID (_id) as request query parameter and get next ten elements starting from the index of id + 1.
I write what i want in mongo shell "language" so that more people understand what i want and can help in shell syntax.
Is there a way to get index of the document by it's _id or may be i can get skip until it in skip().
something like db.collection.find().skip(idOfDocument+1).limit(10)
I found the answer here.
nextDocuments = db.collection.find({'_id'> last_id}).limit(10)

MongoDB $in not only one result in case of repeated elements

I need to get the users whose ids are contained in an array. For this i'm using the $in operator, however being this inside an aggregate operation, i'd like to get back a specific user all the time it's id is present in the array, not just one. For example:
The ids array is A=[a,b,c,b] and U(x) is user with id x
with users.find({_id:{$in:A}}) i get these users as result: U(a),U(b),U(c)
instead i'd like to get back the result: U(a),U(b),U(c),U(b)
so get the user back every time it's id appears.
I understand that $in is working as expected but does anyone have an idea on how can i achieve this?
Thanks
This isn't possible using a MongoDB query.
MongoDB's query engine iterates over the documents in a collection (or over an index if there's a useful one) and returns to you any documents that match your query, in the order it finds them. Whether b appears once, twice, or a hundred times in your query makes no difference: the document with _id of b matches the query and is returned once, when MongoDB finds it.
You can do a post-processing step in your programming language to repeat documents as many times as you want.

Efficient way to transverse mongoDB's indexes with an iterator/pointer?

We are developing a C++ application development tool that uses mongoDB as the underlying database. Say the user has developed a patient collection with fields _id (OID) & patient# with a unique ascending index on patient#. Say there are 10 patients with patient#s 1, 5, 7, 13, 14, 20, 21, 22, 23, 25. Patient# 20 is displayed fetched with limit(1). The user presses PageDown and patient# 21 is displayed -- easy with $gt with patient# = 20.
When the user presses PageUp, patient# 14 should be displayed. My (hopefully wrong) solution is to create a parallel descending index on patient# and $lt. That implies every collection a user creates requires both indexes on the primary key fields to get bidirectional movement. That would apply also to secondary indexes such as name.
Additionally, the user presses F5, is prompted "# of records to move", they enter 3, patient# 23 should be displayed. Or they enter -3, patient# 7 should be displayed. My idea: First use a covered query and return the following 3 patient#s from the index and then fetch the 3rd document. This isn't at all ideal when a less simplified application has hundreds of thousands of documents and the user wants to transverse by 10s of thousands of records. And, again, to achieve the backward movement, I believe I would need that second descending index.
Finally, I need a way to have the user navigate to the last index entry (patient #25). Going to the beginning is trivial. Again, second index?
My question: Is there a way to transverse the ascending index using (say) an iterator or pointer to the current index element and then use iterator/pointer arithmetic to achieve what I want? I.e., +1 will get me the "next" index element from which I could fetch the "next" document; -1 the "previous", +3 the third following, -3 the third previous; index size to the last. Or is there another solution without so much overhead (multiple indexes, large covered queries).
The way to achieve what you want is to have an index on the relevant fields and then do simple queries to get you the records you need when you need them.
It's important to not over-think the problem. Rather than trying to break down how the query optimizer would traverse the index and trying to "reduce" somehow the work it does, just use the queries you need to get the job done.
That means in your case querying for records you need and when the user wants to jump to a particular record querying for that record. If someone is looking at record 27 and they want to go to the next one you can query for smallest record greater than 27 via descending sort and limit(1) qualifier on your find.
I would encourage you to revisit your choice to have basically two primary keys - instead of separate patientID field which has a unique index, you can store patientId in the _id field and get to use the already existing unique index on _id that MongoDB requires in every collection.
A more concrete description of what I am trying to do can be found here:
How to get the previous mongoDB document from a compound index
The answer is: It can't be done in the current version. The 2nd jira ticket is a possible future fix.
See: SERVER-9540
and
SERVER-9547

How to return popped element in mongodb

I would like to pop one item from the array, and get that element.
Is it possible in mongodb?
I didn't find such information at
http://docs.mongodb.org/manual/reference/operator/pop/
This is not possible. MongoDB does not return any part of the document you previously had using a normal update, that being said it can return the full document, not just that popped element on findAndModify ( http://docs.mongodb.org/manual/reference/command/findAndModify/ ), you could then filter that element out, either the first or the last.
NB: I should warn that findAndModify is basically like picking out every document in the query and operating on it, that's how it is able to return it so you might see some performance loss on queries that span a large nummber.
MongoDB operations return full documents.
Options could be to:
Use the findAndModify command and get the popped value of the array program side by processing the returned document. (1 query)
use find to get the document, get the value you want to pop on program side, and send the update. (2 queries)