2

I am working on pagination in flask(Python framework) using flask-paginate (just for ref)

I am able to achieve pagination for just a find query as below:

from flask_paginate import Pagination
from flask_paginate import get_page_args

def starting_with_letter(letter):
    page, per_page, offset = get_page_args()
    collection_name=letter.lower()+'_collection'
    words=db[collection_name]
    data_db=words.find()
    data=data_db.limit(per_page).skip(offset) '''Here I have achieved the limit and skip'''
    pagination = Pagination(page=page, total=data.count(),per_page=per_page,offset=offset,record_name='words')
    return render_template('startingwords.html',data=data,pagination=pagination)

But I am not able to do the same for the aggregate here:

def test():
    page, per_page, offset = get_page_args()
    cursor_list=[]  '''appending each cursor in iteration of for loop '''
    collections=db.collection_names()
    for collection in collections:
        cursor_objects = db[collection].aggregate([
                {
                    "$match": {
                        "$expr": {"$eq": [{"$strLenCP": "$word"}, 6]}
                    }
                },
                            {"$skip": offset},    
                            {"$limit": per_page}

            ])
        for cursor in cursor_objects:
            cursor_list.append(cursor)
    pagination = Pagination(page=page, total=len(cursor_list),per_page=per_page,offset=offset,record_name='words')
    return render_template('lettersearch.html',data=cursor_list,pagination=pagination)

The results are displayed as :

enter image description here

Here all the 39 results are shown at single page

On hitting page 2 it showed :

enter image description here

Note: By default flask-paginate sets initially per_page as 10 and offset as 0

after referring many links i have tried:

placing skip and limit above match which is wrong any way

Also learnt that limit is always followed by skip

I am stuck with this, Any help is appreciated

KcH
  • 3,302
  • 3
  • 21
  • 46
  • Please that code pageSize = param.pageSize; //10 pageNo = param.pageNo; //1,2,3,4,5 const skip = pageSize * (pageNo - 1); const skipCond = {}; skipCond.$skip = skip; commonWhereCond.push(skipCond); const limit = {}; limit.$limit = pageSize; commonWhereCond.push(limit); – Mahesh Bhatnagar Jan 03 '20 at 05:50
  • @MaheshBhatnagar sorry , could not understand the format , would you post as an answer please – KcH Jan 03 '20 at 05:54
  • means you can get skip value using page number. for example : const skip = pageSize * (pageNo - 1); // pazesize =10 , pageNo=1/2/3/4/5 const skipCond = {}; skipCond.$skip = skip; commonWhereCond.push(skipCond); – Mahesh Bhatnagar Jan 03 '20 at 06:01
  • Here skip increments by itself , not bothered of those but the thing is limit and skip are not working here for aggregate – KcH Jan 03 '20 at 06:07
  • Ok i am checking – Mahesh Bhatnagar Jan 03 '20 at 06:19
  • Please tell me what is output from aggregate with limit & skip ? – Mahesh Bhatnagar Jan 03 '20 at 09:12
  • whole records are displayed , i have 39 in total and i am getting 39 after limit and skip too – KcH Jan 03 '20 at 09:14
  • Please use that code db[collection].aggregate([ {"$limit":10} ]) – Mahesh Bhatnagar Jan 03 '20 at 09:18
  • I have tried with all possible ways mate, but none of them worked – KcH Jan 03 '20 at 09:24

1 Answers1

1

Your issue is not with the skip() and limit(); that is working fine. The issue is with your overall logic; you are iterating all 39 collections in the first loop and then appending each result of the aggregation to cursor_list.

I can't figure out the logic of what you are trying to do, as the first example is looking in a words collection and second is looking in all collections for a word field; with that said, you can likely simplify your approach to something like:

offset = 0
per_page = 10
collections = db.list_collection_names()
#
# Add some logic on the collections array to filter what is needed 
#
print(collections[offset:offset+per_page])

EDIT to reflect comments. Full worked example of a function to perform this. No need for an aggregation query - this adds complexity.

from pymongo import MongoClient
from random import randint

db = MongoClient()['testdatabase1']

# Set up some data
for i in range(39):
    coll_name = f'collection{i}'
    db[coll_name].delete_many({}) # Be careful; testing only; this deletes your data
    for k in range (randint(0, 2)):
        db[coll_name].insert_one({'word': '123456'})

# Main function
def test(offset, per_page, word_to_find):
    found = []
    collections = db.list_collection_names()
    for collection in sorted(collections):
        if db[collection].find_one({word_to_find: { '$exists': True}}) is not None:
            found.append(collection)

    print(found[offset:offset+per_page])

test(offset=0, per_page=10, word_to_find='word')
Belly Buster
  • 8,224
  • 2
  • 7
  • 20
  • The reason why I am appending is I want to use that as `data` while rendering template here as: `return render_template('lettersearch.html',data=cursor_list,pagination=pagination)` – KcH Jan 03 '20 at 12:07
  • How would you do that without further appending ? I want to check for the word in all collections ? the same logic in the question , how could i do as you said? – KcH Jan 03 '20 at 12:19
  • check for what word? – Belly Buster Jan 03 '20 at 12:29
  • word i get from request.args.get() , i updated in my question, please have a look – KcH Jan 03 '20 at 12:31
  • Ok have provided an example. – Belly Buster Jan 03 '20 at 12:48
  • The whole thing messed up , as I am looking for all words that are of length `6` here, but i got confused of `word` you mentioned , if it is just a `word` I have did that , but what if I want to search all collections and get all words (every collection might have a match ,so i am looping each collection,get the match which is a cursor object if I'm not wrong and append each object to list) , why I am doing this append is , those all I want to send to template as data ......Hope you got this – KcH Jan 03 '20 at 13:01
  • Can I suggest you start another question with exactly your issue and aim. This has drifted way off course. You need to distill it down to just the issue and provide some data setup example like I did. Otherwise no one will be able to help. – Belly Buster Jan 03 '20 at 13:05
  • Do you have some time now so that I can explain you in chat (10 mins or so) – KcH Jan 03 '20 at 13:07
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/205296/discussion-between-codenewbie-and-belly-buster). – KcH Jan 03 '20 at 13:11