GAE: Making many queries into one - python

I have a productpart database containing a string property named 'type'.
What I'm trying to do is to get all products by a given type (sometimes more then one type).
I've tried to use GAE filter method but can't get it to work properly.
The only solution I've got working is to make a new db.GqlQuery for each type.
The reason I need to fetch each by type is to display them in different 's on the client side?
Is there a way to use just one query for this?
Currently it looks like this :
productPartsEntries = {
'color' : db.GqlQuery("SELECT * FROM ProductParts WHERE type = :type", type = 'color'),
'style' : db.GqlQuery("SELECT * FROM ProductParts WHERE type = :type", type = 'style'),
'size' : db.GqlQuery("SELECT * FROM ProductParts WHERE type = :type", type = 'size')
// add more....
}
..fredrik

You can use the IN operator. It would create the three different queries and group the results together for you under the scenes. See the docs:
GQL does not have an OR operator.
However, it does have an IN operator,
which provides a limited form of OR.
The IN operator compares value of a
property to each item in a list. The
IN operator is equivalent to many =
queries, one for each value, that are
ORed together. An entity whose value
for the given property equals any of
the values in the list can be returned
for the query.
Note: The IN and != operators use multiple queries behind the scenes.
For example, the IN operator executes
a separate underlying datastore query
for every item in the list. The
entities returned are a result of the
cross-product of all the underlying
datastore queries and are
de-duplicated. A maximum of 30
datastore queries are allowed for any
single GQL query.

Related

How to get dynamodb to only return certain columns

Hello, I have a simple dynamodb table here filled with placeholder values.
How would i go about retrieving only sort_number, current_balance and side with a query/scan?
I'm using python and boto3, however, just stating what to configure for each of the expressions and parameters is also enough.
Within the Boto3 SDK you can use:
get_item if you're trying to retrieve a specific value
query, if you're trying to get values from a single partition (the hash key).
scan if you're trying to retrieve values from across multiple parititions.
Each of these have a parameter named ProjectionExpression, using this parameter provides the following functionality
A string that identifies one or more attributes to retrieve from the specified table or index. These attributes can include scalars, sets, or elements of a JSON document. The attributes in the expression must be separated by commas.
]You would specify the attributes that you want to retrieve comma separated, be aware that this does not reduce the cost of RCU that is applied for performing the interaction.
table = dynamodb.Table('tablename')
response = table.scan(
AttributesToGet=['id']
)
This works. but this method is deprecated, using Projections is recommended
to return only some fields you should use ProjectionExpression in the Query configuration object, this is an string array with all the fields:
var params = {
TableName: 'TableName',
KeyConditionExpression: '#pk = :pk AND #sk = :sk',
ExpressionAttributeValues: {
':pk': pk,
':sk': sk,
},
ExpressionAttributeNames: {
'#sk':'sk',
'#pk':'pk'
},
ProjectionExpression:['sort_number', 'current_balance','side']
};

How to perform a JOIN in Salesforce (SOQL) - Simple Salesforce (Python Library)

I am using simpleSalesforce library for python to query SalesForce.
I am looking at two different object in SalesForce: Account and Opportunity (parent-child). There is an accountId inside the opportunity object.
I am trying to perform an inner join between the two and select the results (fields from both objects).
a normal SQL statement would look like this:
SELECT acc.Name, opp.StageName
FROM Account AS acc
JOIN Opportunity AS opp ON acc.Id = opp.AccountId
I am not sure how to translate this kind of query into SOQL.
A couple notes about SOQL:
No aliases allowed
No explicit joins allowed
But with that in mind, it's still possible to get the outcome you want by directly using the desired fields names as an "attribute" of the object relationship. Example:
SELECT account.Name, Name, StageName FROM Opportunity
Which will grab the related account name, the opportunity name, and the opportunity stage name in one query.
As long as the field on your base object is of a type Lookup or Master-Detail, you can use this type of relationship. In the case of custom fields, you switch the __c over to __r though.
Example:
Opportunity has a relationship to custom object Address__c and we want to know what city & country these opportunities are in:
SELECT Address__r.Country__c, Address__r.City__c,Name, StageName from Opportunity
Salesforce doesn't allow arbitrary joins. You must write relationship queries to traverse predefined relationships in the Salesforce schema.
Here, you'd do something like
SELECT Name, (SELECT StageName FROM Opportunities)
FROM Account
No explicit join logic is required, or indeed permitted. Note too that your return values will be structured, nested JSON objects - Salesforce does not return flat rows like a SQL query would.

Django - Filter GTE LTE for alphanumeric IDs

I am trying to serve up our APIs to allow filtering capabilities using LTE and GTE on our ID look ups. However, the IDs we have are alphanumeric like AB:12345, AB:98765 and so on. I am trying to do the following on the viewset using the Django-Filter:
class MyFilter(django_filters.FilterSet):
item_id = AllLookupsFilter()
class Meta:
model = MyModel
fields = {
'item_id': ['lte', 'gte']
}
But the issue is, if I query as: http://123.1.1.1:7000/my-entities/?item_id__gte=AB:1999 or even http://123.1.1.1:7000/my-entities/?item_id__lte=AB:100 it won't exactly return items with ID's greater than 1999 or less than 100 since the filter will take ID as a string and tries to filter by every character. Any idea how to achieve so I can filter on IDs so I get items exactly greater / less than the numeric ID (ignoring the initial characters) ?
What you'll want to do is write a custom lookup. You can read more about them here: https://docs.djangoproject.com/en/2.0/howto/custom-lookups/
The code sample below has everything you need to define your own except the actual function. For that part of the example check the link.
from django.db.models import Lookup
#Field.register_lookup
class NotEqual(Lookup):
lookup_name = 'ne'
In the lookup, you'll need to split the string and then search based on your own parameters. This will likely require you to do one of the following:
Write custom SQL that you can pass through Django into your query.
Request a large number of results containing the subset you're looking for and filter that through Python, returning only the important bits.
What you're trying to accomplish is usually called Natural Sorting, and tends to be very difficult to do on the SQL side of things. There's a good trick, explained well here: https://www.copterlabs.com/natural-sorting-in-mysql/ However, the highlights are simple in the SQL world:
Sort by Length first
Sort by column value second

What is the difference between with_entities and load_only in SQLAlchemy?

When querying my database, I only want to load specified columns. Creating a query with with_entities requires a reference to the model column attribute, while creating a query with load_only requires a string corresponding to the column name. I would prefer to use load_only because it is easier to create a dynamic query using strings. What is the difference between the two?
load_only documentation
with_entities documentation
There are a few differences. The most important one when discarding unwanted columns (as in the question) is that using load_only will still result in creation of an object (a Model instance), while using with_entities will just get you tuples with values of chosen columns.
>>> query = User.query
>>> query.options(load_only('email', 'id')).all()
[<User 1 using e-mail: n#d.com>, <User 2 using e-mail: n#d.org>]
>>> query.with_entities(User.email, User.id).all()
[('n#d.org', 1), ('n#d.com', 2)]
load_only
load_only() defers loading of particular columns from your models.
It removes columns from query. You can still access all the other columns later, but an additional query (in the background) will be performed just when you try to access them.
"Load only" is useful when you store things like pictures of users in your database but you do not want to waste time transferring the images when not needed. For example, when displaying a list of users this might suffice:
User.query.options(load_only('name', 'fullname'))
with_entities
with_entities() can either add or remove (simply: replace) models or columns; you can even use it to modify the query, to replace selected entities with your own function like func.count():
query = User.query
count_query = query.with_entities(func.count(User.id)))
count = count_query.scalar()
Note that the resulting query is not the same as of query.count(), which would probably be slower - at least in MySQL (as it generates a subquery).
Another example of the extra capabilities of with_entities would be:
query = (
Page.query
.filter(<a lot of page filters>)
.join(Author).filter(<some author filters>)
)
pages = query.all()
# ok, I got the pages. Wait, what? I want the authors too!
# how to do it without generating the query again?
pages_and_authors = query.with_entities(Page, Author).all()

How to filter by joinloaded table in SqlAlchemy?

Lets say I got 2 models, Document and Person. Document got relationship to Person via "owner" property. Now:
session.query(Document)\
.options(joinedload('owner'))\
.filter(Person.is_deleted!=True)
Will double join table Person. One person table will be selected, and the doubled one will be filtered which is not exactly what I want cuz this way document rows will not be filtered.
What can I do to apply filter on joinloaded table/model ?
You are right, table Person will be used twice in the resulting SQL, but each of them serves different purpose:
one is to filter the the condition: filter(Person.is_deleted != True)
the other is to eager load the relationship: options(joinedload('owner'))
But the reason your query returns wrong results is because your filter condition is not complete. In order to make it produce the right results, you also need to JOIN the two models:
qry = (session.query(Document).
join(Document.owner). # THIS IS IMPORTANT
options(joinedload(Document.owner)).
filter(Person.is_deleted != True)
)
This will return correct rows, even though it will still have 2 references (JOINs) to Person table. The real solution to your query is that using contains_eager instead of joinedload:
qry = (session.query(Document).
join(Document.owner). # THIS IS STILL IMPORTANT
options(contains_eager(Document.owner)).
filter(Person.is_deleted != True)
)

Categories

Resources