Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ndb Query partial string matching

This seems like it should be an easy question. But the docs don't seem to answer it. Using the example from them, I want to do this:

Account.query(Account.title == "best")

Except I want to match partial strings as well. So in this scenario:

acct = Account(title="the best account in the world")

an ndb query with argument "best" would match the acct.

The only option I see at the moment is to loop through Account.query() and match each title with re.search module in python. This doesn't seem like a good solution.

Update: I am also looking at gql. Doing this:

acct = ndb.gql('SELECT * from Account WHERE title LIKE '%best%')

returns a Parse Error: Invalid WHERE Condition at symbol LIKE

like image 276
mehulkar Avatar asked Jan 12 '13 09:01

mehulkar


People also ask

How to run a partial match query in Python?

You can use the autocomplete, phrase , regex, and wildcard operators to run a case-sensitive partial match query. This tutorial uses these operators to search for movies whose plot contain the specified partial string. The query uses the following pipeline stages:

How do I return a partial string with a query?

To return matches for partial string queries, you can use one of the following operators: The autocomplete operator, which allows you to search the specified fields for a word or phrase that contains the sequence of characters that you specify with your query.

How to find out the results containing partial match strings in Excel?

We can find out the results containing partial match strings by using the IF ISNUMBER SEARCH combo. Consider a data set containing the column “Name”, “Match String”, “Status”. We need to identify the names that containing the partial match string from the column “Match String”. Apply the IF ISNUMBER SEARCH formula in the “Status” column in cell D4

How do I search on a pattern or a partial term?

If you need to search on a pattern or a partial term such as "10-NOR", the query engine now has the basis for finding a match. Be aware that query parsers often lower-case terms in a search expression when building the query tree.


3 Answers

NOTE : This does not exactly answer the question, but someone looking for starts with might find this answer useful.

NDB's String field is indexed in a way where you can do greater than (>=) and less than (<) search. Assuming the following Person model:

class Person(ndb.Model):
    name         = ndb.StringProperty()
    name_lower   = ndb.ComputedProperty(lambda self: self.name.lower())

You can do the following:

def search_by_text(text):
  text = text.lower()
  limit = text[:-1] + chr(ord(text[-1]) + 1)
  return Person.query(Person.name_lower >= text, Person.name_lower < limit).fetch(50)

p = search_by_text('kri')

The limit variable in this example will contain the string 'krj' and becomes the limit of the search values. The above will get you all the people whose name is greater than kri but less than krj and limit to the first 50 findings. Because of the limit, names like kross and lark will be filtered out.

Note: it's important that you have an ndb.ComputedProperty to contain a lower case version of the field you want to search on. Don't forget to add that!

like image 128
Kris Subramanian Avatar answered Oct 17 '22 06:10

Kris Subramanian


GQL doesn't have wildcards matching, to achieve that you will need to use the full text search.

like image 45
Shay Erlichmen Avatar answered Oct 17 '22 04:10

Shay Erlichmen


For a (presumably) short field like a title, adding a repeated StringProperty that contains each word of the title (ignoring stop words, maybe) would allow you to match on words, and would be simpler than using the search API.

like image 3
Greg Avatar answered Oct 17 '22 06:10

Greg