views:

96

answers:

3

Hi All,

Is there some way to implement Django like contains or icontains filters with Google App Engine as well? I am using app engine patch.

I have used the below query earlier to match the start of a string but now the requirement is to find a string pattern within Datastore.

Employee.all().filter('name >=',value).filter('name <',unicode(value) + u'\ufffd')

Basically the requirement is to implement a search functionality with all the strings containing the search string as a result.

Please suggest.

Thanks in advance.

A: 

No, a true substring search isn't really possible in the datastore.

The best you could do would be to add a keyword index and do the "begins with" type query from your question on that, but even then for an entity like "foo bar baz" you could match when searching for "ba" but not "ar b".

This sounds like a great job for BigQuery, which is in preview right now with a wait list to get access.

Wooble
BigQuery is designed for offline analytical processing, not fulltext search.
Nick Johnson
@Wooble, thanks for your reply. Can you please elaborate or provide an example code of what you have mentioned. In my current code, "foo bar baz" would appear in result only when I search "foo" i.e. the start of the string itself and would not search "bar" or "baz".
anand
I am trying with whoosh as well but if I enter only one character to search, it gives a 'NoneType' object has no attribute 'doc_scores' error message.
anand
A: 

Recently I ran into the same problem and made my own model manager with an overriden filter function that also understands __contains. I'm assuming you're using Django.

class UserFeedManager(models.Manager):    
    def filter(self, *args, **kwargs):
        keywordargs = {}
        for (arg, val) in kwargs.items():
            if '__contains' in arg:
                contains.append((arg.split('__')[0], val))
            else:
                keywordargs[arg] = val

        result = []
        if len(contains) > 0:
            for entry in super(UserFeedManager, self).filter(*args, **keywordargs):
                if all(map(lambda (attr, val): val in entry.__getattribute__(attr),
                           contains)):
                    result.append(entry)
        else:
            result = super(UserFeedManager, self).filter(*args, **keywordargs)

        return result

Essentially it builds a list of arguments that have a __contains, then fetches the whole result and filters it to only hold the results that pass all criteria.

Swizec Teller
+1  A: 

What you need to do is create a string list property with the different string permutations and query on that list.

Take a look at appengine.ext.search.SearchableModel for an example implementation Ypu can also check out http://www.allbuttonspressed.com/projects/nonrel-search

Eran Kampf
perfect, this is what I was looking for. Thanks Eran.
anand