Example #1
0
  def name_has_prefix(name, prefix):
    prefixes = prefix.split()

    for name_part in search_namify(name).split():
      check_prefixes = prefixes
      for prefix in check_prefixes:
        if name_part.startswith(prefix):
          prefixes.remove(prefix)
          if len(prefixes) == 0:
            return True
            break

    return False
Example #2
0
  def autocomplete(cls, prefix):
    prefix = prefix.lower().strip()

    # Go into memory and grab all (some?) of the caches for this
    # prefix and earlier
    cache_list = [SetQueryCache.fetch(cls.COMPLETE %prefix[:i+1]) for
                  i in range(len(prefix))]

    best_data = set()
    for prelen, cached_query in enumerate(cache_list):
      if len(cached_query) > 0:
        best_data = cached_query.results
      else:
        best_data = set(
          filter(lambda an: ArtistName.name_has_prefix(an, prefix[:prelen+1]),
                 best_data))
        cached_query.set(best_data)
        cached_query.save()

    cached = cache_list.pop() # Get the cache for the relevant prefix
    if cached.need_fetch(cls.AC_FETCH_NUM):
      # We have to fetch some keys from the datastore
      if cached.cursor is None:
        cached.cursor = {'lower': None, 'search': None}

      # Prep the queries
      lower_query = RawArtistName.query().filter(
        ndb.AND(RawArtistName.lowercase_name >= prefix,
                RawArtistName.lowercase_name < (prefix + u"\ufffd")))
      search_query = RawArtistName.query().filter(
        ndb.AND(RawArtistName.search_name >= prefix,
                RawArtistName.search_name < (prefix + u"\ufffd")))

      try:
        # Try to continue an older query
        num = cls.AC_FETCH_NUM - len(cached)

        lower_raw_artists, lower_cursor, l_more = lower_query.fetch_page(
          num, start_cursor=cached.cursor['lower'],
          projection=[RawArtistName.artist_name])
        search_raw_artists, search_cursor, s_more = search_query.fetch_page(
          num, start_cursor=cached.cursor['search'],
          projection=[RawArtistName.artist_name])

        cache_results = cached.results

      except db.BadRequestError:
        # Unable to continue the older query. Run a new one.
        lower_raw_artists, lower_cursor, l_more = lower_query.fetch_page(
          num,
          projection=[RawArtistName.artist_name])
        search_raw_artists, search_cursor, s_more = search_query.fetch_page(
          num,
          projection=[RawArtistName.artist_name])

        cache_results = set()

      add_artists = (set(a.artist_name for a in search_raw_artists) |
                     set(a.artist_name for a in lower_raw_artists))
      artist_names = cached.results | add_artists

      # We've got a bunch of artistnames for this prefix, so let's
      # update all of our cached queries: this one, and all supqueries
      cached.extend_by(add_artists,
                       {'lower': lower_cursor, 'search': search_cursor},
                       l_more or s_more)
      cached.save()

      for cached_query in reversed(cache_list):
        cached_query.extend(add_artists)
        cached_query.save()
    else:
      # We don't have to fetch anything!
      artist_names = cached.results

    return sorted(artist_names, key=lambda x: search_namify(x))