Google App Engine - ndb sorting by string? (Python) - python

Is it possible to sort query results by StringProperty?
I have the following:
class User(ndb.Model):
first_name = ndb.StringProperty(indexed=False)
last_name = ndb.StringProperty(indexed=False)
Now if I want to retrieve the stored entries from the database, I use this (it works):
user_query = User.query(ancestor=user_key(user_name))
But I want the result to be ordered by first_name, so I use this:
user_query = User.query(ancestor=user_key(user_name)).order(-User.first_name)
This DOES NOT work! I don't know what is wrong and it does not produce any errors, but no results show up anymore. All I get is an empty table :-(

You need an index for order to work.

Related

How to store dynamic form value into datastore using Google App Engine

I am creating a dynamic form in html template to obtain the currency pair that user select. The form looks like this:
The user can dynamically add and remove currency. I used a Jquery to generate different currency pairs name of currency_n for the nth currency.
My best question is how to store those into datastore.
If user only create one currency pair (i.e. The form is not dynamic), the get.request should be
def post(self):
user_currency_1_1 = self.request.get('currency_1_1')
user_currency_1_2 = self.request.get('currency_1_2')
I didnt know how many currency pairs does customer submit, how to get the correct value? Also, how to design the datastore structure to store those dynamic content?
class currency(db.Model):
user = db.EmailProperty(required = True)
currency = db.StringProperty(required = True)
I hesitate to even answer, as you have not responded to answers in your last question. We are not here to write your code for you. But, you are fortunate that SO users are generous with their time.
Following up on my last answer:
from google.appengine.ext import ndb
class UserCurrencies(ndb.Model):
user_email = ndb.StringProperty()
currencies = ndb.JsonProperty(indexed=False)

What type of result SQLAlchemy query() returns?

I've got a table in my database
class Operator(db.Model):
id = db.Column(db.Integer, primary_key=True)
login = db.Column(db.String(100))
calls = db.relationship('Call', backref='operator', lazy='dynamic')
and I want to get all login from this table. So I do
operators = db.session.query(models.Operator.login).all()
print(operators)
And I suppose to get a list of logins but in fact I've got a list of tuples
[('ivanov',), ('petrov',)]
Of course I can manage this data but I can't understand why it's formatted in that way? Why it has empty second element in every tuple? Maybe I do something wrong and there is easier way to get list of logins?
If you want to get a list of logins something like this will do what you need:
operators = db.session.query(Operator).all()
operators = [op.login for op in operators]
The tuple representation is the standard.

Is it possible to set the constraint unique = True except for empty string into SQLAlchemy?

I use the following column in my table:
email = Column(String(60), unique=True)
However, I need the possibility to save empty strings in this column. Namely, I need something like this:
email = Column(String(60), unique=True, blank=True)
but it doesn't work. Is it possible to implement this within SQLAlchemy? What is correspondent SQL (Postgresql dialect)?
You have to try to set not an empty string, but a NULL istead. As it's said in PostgreSql documentation NULL-values are not equals.

Efficient way to do large IN query in Google App Engine?

A user accesses his contacts on his mobile device. I want to send back to the server all the phone numbers (say 250), and then query for any User entities that have matching phone numbers.
A user has a phone field which is indexed. So I do User.query(User.phone.IN(phone_list)), but I just looked at AppStats, and is this damn expensive. It cost me 250 reads for this one operation, and this is something I expect a user to do often.
What are some alternatives? I suppose I can set the User entity's id value to be his phone number (i.e when creating a user I'd do user = User(id = phone_number)), and then get directly by keys via ndb.get_multi(phones), but I also want to perform this same query with emails too.
Any ideas?
You could create a PhoneUser model like so:
from google.appengine.ext import ndb
class PhoneUser(ndb.Model):
number = ndb.StringProperty()
user = ndb.KeyProperty()
class User(ndb.Model):
pass
u = User()
u.put()
p = PhoneUser(id='123-456-7890', number='123-456-7890', user=u.key)
p.put()
u2 = User()
u2.put()
p2 = PhoneUser(id='555-555-5555', number='555-555-5555', user=u2.key)
result = ndb.get_multi([ndb.Key(PhoneUser, '123-456-7890'), ndb.Key(PhoneUser, '555-555-5555')])
I think that would work in this situation. You would just have to add/delete your PhoneUser model whenever you update your User. You can do this using post hooks: https://developers.google.com/appengine/docs/python/ndb/modelclass#Model__post_delete_hook
I misunderstood part of your problem, I thought you were issuing a query that was giving you 250 entities.
I see what the problem is now, you're issuing an IN query with a list of 250 phone numbers, behind the scenes, the datastore is actually doing 250 individual queries, which is why you're getting 250 read ops.
I can't think of a way to avoid this. I'd recommend avoiding searching on long lists of phone numbers. This seems like something you'd need to do only once, the first time the user logs in using that phone. Try to find some way to store the results and avoid the query again.
there is no efficient way to do an IN query.
so instead avoid it all together.
how?
invert the query, instead of finding all people that belong to this guys phone list.
try
finding all people that have this users phoneid in their list.
this however is not without some extra cost.
the phonelist for each user much be stored and indexed.
class User(ndb.Model):
phoneList = ndb.PropertyList()
phone_id= ndb.StringProperty()
select from where User.phoneList = :this_phone_number

Selecting Datastore ID in Google App Engine?

I'm trying to make a query that selects everything where the id is 6. The problem is that I cant seem to get it to work. This is what the code looks like at the moment:
query = db.GqlQuery("SELECT * FROM Users WHERE id = 6")
result = query.get()
for result in query:
self.response.out.write(result.username)
Theres no errors or anything but it just wont output the username. Has anyone had this problem before or know what I did wrong?
If you're using the id value assigned by the datastore, there can only be a single entity with a given id.
How about this instead:
idNum = 6
# handy function the datastore API provides...
user = Users.get_by_id(idNum)
self.response.out.write(user.username)

Categories

Resources