gqlquery for no values in ListProperty - google-app-engine

I have this code to find all the nodes where property branches is empty.
nobranches=TreeNode.all()
for tree in nobranches:
if tree.branches==[]:
I wanted to find a better, more efficient way to do this. A meathod where I don't have to retrieve all the TreeNodes. I have tried TreeNode.all().filter(branches=[]) but this gives me a message, "BadValueError('Filtering on lists is not supported'" . How can I do something like TreeNode.gql('WHERE branches=:1', []).fetch(100). I tried this, but I get a "BadValueError: May not use the empty list as a property value; property is []". Is there any other efficient way?
BTW, Here is what TreeNode looks Like
class TreeNode(db.Model):
name = db.StringProperty()
branches =db.ListProperty(db.Key)

You can't do this with a filter: as Saxon says, there's no index row matching what you want to retrieve, and so no way to retrieve it.
One simple alternative is to store another property that contains the number of elements in the list, and filter on that. aetycoon is a library that contains computed properties that may help with that:
class TreeNode(db.Model):
name = db.StringProperty()
branches = db.ListProperty(db.Key)
branch_count = aetycoon.DerivedProperty(lambda self: len(self.branches))

The documentation on how indexes are stored says:
For multi-valued properties, such as ListProperty and StringListProperty, each value has its own index row, so using multi-valued properties does result in more indexing overhead.
So for each item in your list property, there is a row in the index.
My expectation would be that if there are no items in the list property, then there would be no rows in the index. So it wouldn't be possible to use the index to retrieve entities with an empty list.
One solution would be to add another property (eg hasbranches = db.BooleanProperty()), which you maintain when you add or remove branches. Then you will be able to filter for hasbranches = False.

Related

Query objects where the pointer object matches any objects within a PFObject array

My class Posts has a column that is a pointer to another class called Styles. Each post must be associated to a Style object as a rule of thumb.
My problem: I can't get only the posts that are associated to one or more styles.
My object selectedStyles, that is an array of PFObjects that already contains the style objects I would like to use to match the query. So populating the selectedStyles is not an issue, but how to use it to produce my query is.
What I am doing at the moment is:
override func queryForTable() -> PFQuery {
var query = PFQuery(className: "Posts")
query.whereKey("bellongsToStyle", containsAllObjectsInArray: [selectedStyles])
query.orderByDescending("createdAt")
return query
If I could translate the whereKey method in plain english I would say:
...contains - ANY OF THE - PFObjectsInArray [selectedStyles]
I am not so sure if that is possible... any ideas?!
I think I am too late for this but you can just add
[IncludeKey:"bellongsToStyle"]
when you are querying in your 'Posts' class
don't need to run any extra query for that
here's a small reference
http://blog.parse.com/announcements/queries-for-relational-data/

Finding Descendant Item Sets

Let's say I have these Models:
class Category(MP_Node):
name = models.CharField(max_length=30)
class Item(models.Model):
category = models.ForeignKey(Category)
and I would like to find all Items belonging to any descendant of a given Category.
Usually I would write category.item_set but this is just Items belonging to the given level of the hierarchy.
Using the example tree in the treebeard tutorial, if an Item belongs to "Laptop Memory", how would I find all Items belonging to descendants "Computer Hardware" where "Laptop Memory" is one of those descendants?
I just had the same problem and figured out how to do it (consider it inside the function get_queryset of a ListView):
category = Category.objects.filter(slug=self.kwargs['category']).get()
descendants = list(category.get_descendants().all())
return self.model.objects.select_related('category').filter(category__in=descendants+[category, ])
Another option that I came up with was using a filter with 'OR':
from django.db.models import Q
category = Category.objects.filter(slug=self.kwargs['category']).get()
descendants = list(category.get_descendants().all())
return self.model.objects.select_related('category').filter(Q(category__in=category.get_descendants()) | Q(category=category))
I looked at the treebeard code to see how it gets descendants of a node. We can apply the same filters as a related field lookup.
paramcat = Category.objects.get(id=1) # how you actually get the category will depend on your application
#all items associated with this category OR its descendants:
items = Item.objects.filter(category__tree_id=paramcat.tree_id, category__lft__range=(paramcat.lft,paramcat.rgt-1))
I think using intermediate calls like get_descendants will result in one query per descendant, plus load all descendants into memory. It defeats the purpose of using treebeard in the first place
I'd be interested in seeing a custom lookup based on this code, I'm not sure how to do it...

Backbone collection: Retrieve distinct values of a collection

I have backbone collection of models and would like to retrieve the distinct values of a certain property
If I have loaded data like the following into my collection:
[{brand:'audi',id:'1234'},
{brand:'audi',id:'3456'},
{brand:'bmw',id:'3456'}]
I would now want to get the distinct brands from the collection. The result should be:
['audi','bmw']
Looking at the Backbone and Underscore API I don't see anything obvious to achieve this.
My current approach would be to use a library like jslinq
Am I missing anything obvious or does somebody have a better suggestion than jslinq?
You can use pluck and then use uniq (example: http://jsfiddle.net/sCVyN/5/)
pluck
A convenient version of what is perhaps the most common use-case for
map: extracting a list of property values.
uniq
Produces a duplicate-free version of the array, using === to test
object equality. If you know in advance that the array is sorted,
passing true for isSorted will run a much faster algorithm. If you
want to compute unique items based on a transformation, pass an
iterator function.

How to find entries which has not empty StringListProperty?

I have a following model in the Google appengine app.
class TestModel(db.Model):
names = db.StringListProperty(required=False)
So, I want to get entries which has not empty in names property. I tried like this.
TestModel.all().filter('names !=', [])
But it raises the exception: BadValueError: Filtering on lists is not supported
How can I filter it? or Should I check one by one like following?
for entry in TestModel.all():
if len(entry.names) > 0:
result.append(entry)
Try this:
TestModel.all().filter('names >=', None)
This will give you every entity with at least one value set for names, i.e. every value in the index.

App Engine: Filter for Choosing Entities with a Specific Item Present in their ListProperties

I need to filter entities based on one of their ListProperties having a certain element present. So kind of like:
entities.filter('listProp IN ',element) except where listProp and element are reversed if you see what I mean.
Anyone know how to filter like this?
If I understand you correctly, you want to find all entities which have that particular element present. You should be able to use: entities.filter('listProp =', element)
Look at: http://code.google.com/appengine/docs/python/datastore/typesandpropertyclasses.html#ListProperty
It says, "list_property = value tests if the value appears anywhere in the list".
Ok so it turns out the IN equality clause takes care of this case for lists automatically.
As in it does a for ... each on the list of elements to be searched for and if any one of them is present in the ListProperty for each entity it will return that entity.

Resources