1
votes

I am creating a sample application storing user detail along with its class information.

Modal classes being used are :

Model class for saving user's class data

class MyData(ndb.Model):
    subject =  ndb.StringProperty()
    teacher = ndb.StringProperty()
    strength = ndb.IntegerProperty()
    date = ndb.DateTimeProperty()

Model class for user

class MyUser(ndb.Model):
    user_name = ndb.StringProperty()
    email_id = ndb.StringProperty()
    my_data = ndb.StructuredProperty(MyData, repeated = True)

I am able to successfully store data into the datastore and can also make simple query on the MyUser entity using some filters based on email_id and user_name.

But when I try to query MyUser result using filter on a property from the MyUser modal's Structured property that is my_data, its not giving correct result.

I think I am querying incorrectly. Here is my query function

function to query based upon the repeated structure property

def queryMyUserWithStructuredPropertyFilter():
    shail_users_query = MyUser.query(ndb.AND(MyUser.email_id == "[email protected]", MyUser.my_data.strength > 30))
    shail_users_list = shail_users_query.fetch(10)

    maindatalist=[]

    for each_user in shail_users_list:
        logging.info('NEW QUERY :: The user details are : %s %s'% (each_user.user_name, each_user.email_id))

    # Class data
        myData = each_user.my_data
        for each_my_data in myData:
            templist = [each_my_data.strength, str(each_my_data.date)]
            maindatalist.append(templist)

            logging.info('NEW QUERY :: The class data is : %s %s %s %s'% (each_my_data.subject, each_my_data.teacher, str(each_my_data.strength),str(each_my_data.date)))

    return maindatalist

I want to fetch that entity with repeated Structured property (my_data) should be a list which has strength > 30.

Please help me in knowing where I am doing wrong.

Thanks.

1
Querying for repeated structured properties is done as you are doing it, so that looks ok... What are you expecting to see and what are you actually getting? (BTW: You don't need to use ndb.AND when you query for email_id and my_data.strength: AND is the default there) - marianosimone
Actually filter is not working correctly. For that particular MyUser entity I have been adding multiple structured property of type MyData as you can see in the modals. I need the final data with only those MyData properties for which class strength is greater than 30. But when I do query , no filtering happens and I get all the MyData properties saved. - Napolean
The query in line 2 is going to return all MyUser objects that have at least one MyData in their my_data property with strength > 30 (you are querying over MyUser). I'm adding an answer now with the full code to achieve what you want - marianosimone

1 Answers

2
votes

Queries over StructuredProperties return objects for which at least one of the structured ones satisfies the conditions. If you want to filter those properties, you'll have to do it afterwards.

Something like this should do the trick:

def queryMyUserWithStructuredPropertyFilter():
    shail_users_query = MyUser.query(MyUser.email_id == "[email protected]", MyUser.my_data.strength > 30)
    shail_users_list = shail_users_query.fetch(10)

    # Here, shail_users_list has at most 10 users with email being
    # '[email protected]' and at least one element in my_data
    # with strength > 30

    maindatalist = [
        [[data.strength, str(data.date)] for data in user.my_data if data.strength > 30] for user in shail_users_list
    ]

    # Now in maindatalist you have ONLY those my_data with strength > 30
    return maindatalist