hyang123
hyang123

Reputation: 1280

Google App Engine: autocomplete search for entity name

I'm building a 'jobs' or 'professional resume' webapp. Here's my data model set up:

I have a resume Model:

class Resume(ndb.Model):
    full_name = ndb.StringProperty(required = True)
    education = ndb.StructuredProperty(Education, repeated = True)
    experience = ndb.StructuredProperty(Experience, repeated = True)
    skill = ndb.StructuredProperty(Skill, repeated = True)

Here is the Skill(ndb.Model) for the skill ndb.StructuredProperty(Skill) inside the Resume(ndb.Model):

class Skill(ndb.Model):
    skill = ndb.StringProperty(required = True)
    description = ndb.TextProperty()

I'd like to achieve the following:

Thank you for any tip.

Upvotes: 1

Views: 1424

Answers (1)

Dmytro Sadovnychyi
Dmytro Sadovnychyi

Reputation: 6201

Read about filtering by structured properties here. For you case query will look like: Resume.query(Resume.skill.skill == 'python').fetch(10)

Autocompleting is a little big harder to do on app engine. You can use prefix queries for this. I think that you should store all available skills in separate kind with key as lower cased skill name. "Python" -> ndb.Key('Skills', 'python')

def query_by_prefix(model, prefix):
  """ Returns NDB query with filter by key prefix.
  """
  prefix = str(prefix)
  return (model.query(ndb.AND(model.key >= ndb.Key(model, prefix),
                              model.key <= ndb.Key(model, prefix + u'\ufffd'))))
class Skills(ndb.Model):
   """ Save here some skills just with keys.
   """
   pass
skills = query_by_prefix(Skills, 'p').fetch(10)  # you will get up to 10 skills which starts with "p".

You should think about memcaching autocomplete related stuff. This operations will be quoted as "Read", not "Small" operation. It's also possible to build autocomplete by saving all possible prefixes with words into datastore. Here some sample code...

class Autocomplete(ndb.Model):
  """ Key here is first letter of the skill. Skills with the same letter should be saved in one entity. 
  """
  skills = ndb.PickleProperty()

# populate our Autocomplete model first.. 
all_skills = ['python', 'app-engine', 'django', 'java', 'android']
d = dict()
[d.setdefault(w[0:1], []).append(w) for w in all_skills]  # build dict like {'a': ['android', 'app-engine']}
ndb.put_multi([Autocomplete(key=ndb.Key(Autocomplete, k), skills=d[k]) for k in d.keys()])   # put all this stuff into model...

# do the query
query = 'a'
results = Autocomplete.get_by_id(query[0:1].lower())

You will see android and app-engine in results. But it's easy to filter them in memory depending on query. For big datasets you will need to improve this method.

Upvotes: 5

Related Questions