def _ToPb(self, *args, **kwds): """Adds filters for the search query, then delegates to the superclass. Mimics Query._ToPb()'s signature. Raises BadFilterError if a filter on the index property already exists. Returns: datastore_pb.Query """ properties = getattr(self, "_properties", ALL_PROPERTIES) index_property_name = SearchableEntity.IndexPropertyName(properties) if index_property_name in self: raise datastore_errors.BadFilterError('%s is a reserved name.' % index_property_name) pb = super(SearchableQuery, self)._ToPb(*args, **kwds) if hasattr(self, '_search_query'): keywords = SearchableEntity._FullTextIndex( self._search_query, self._word_delimiter_regex) for keyword in keywords: filter = pb.add_filter() filter.set_op(datastore_pb.Query_Filter.EQUAL) prop = filter.add_property() prop.set_name(index_property_name) prop.set_multiple(len(keywords) > 1) prop.mutable_value().set_stringvalue( unicode(keyword).encode('utf-8')) return pb
def _ToPb(self, limit=None, offset=None): """Adds filters for the search query, then delegates to the superclass. Raises BadFilterError if a filter on the index property already exists. Args: # an upper bound on the number of results returned by the query. limit: int # number of results that match the query to skip. limit is applied # after the offset is fulfilled. offset: int Returns: datastore_pb.Query """ if SearchableEntity._FULL_TEXT_INDEX_PROPERTY in self: raise datastore_errors.BadFilterError( '%s is a reserved name.' % SearchableEntity._FULL_TEXT_INDEX_PROPERTY) pb = super(SearchableQuery, self)._ToPb(limit=limit, offset=offset) if hasattr(self, '_search_query'): keywords = SearchableEntity._FullTextIndex( self._search_query, self._word_delimiter_regex) for keyword in keywords: filter = pb.add_filter() filter.set_op(datastore_pb.Query_Filter.EQUAL) prop = filter.add_property() prop.set_name(SearchableEntity._FULL_TEXT_INDEX_PROPERTY) prop.set_multiple(len(keywords) > 1) prop.mutable_value().set_stringvalue(unicode(keyword).encode('utf-8')) return pb
def GetFilterPredicate(self, *args, **kwds): """Adds filters for the search query, then delegates to the superclass. Mimics Query.GetFilterPredicate()'s signature. Raises BadFilterError if a filter on the index property already exists. Returns: datastore_query.FilterPredicate """ properties = getattr(self, "_properties", ALL_PROPERTIES) index_property_name = SearchableEntity.IndexPropertyName(properties) if index_property_name in self: raise datastore_errors.BadFilterError('%s is a reserved name.' % index_property_name) filter = super(SearchableQuery, self).GetFilterPredicate(*args, **kwds) if hasattr(self, '_search_query'): keywords = SearchableEntity._FullTextIndex( self._search_query, self._word_delimiter_regex) if keywords: search_filter = datastore_query.make_filter( index_property_name, '=', list(keywords)) if filter: filter = datastore_query.CompositeFilter( datastore_query.CompositeFilter.AND, [filter, search_filter]) else: filter = search_filter return filter
def _ToPb(self, limit=None): """Adds filters for the search query, then delegates to the superclass. Raises BadFilterError if a filter on the index property already exists. Args: # an upper bound on the number of results returned by the query. limit: int Returns: datastore_pb.Query """ if SearchableEntity._FULL_TEXT_INDEX_PROPERTY in self: raise datastore_errors.BadFilterError( '%s is a reserved name.' % SearchableEntity._FULL_TEXT_INDEX_PROPERTY) pb = super(SearchableQuery, self)._ToPb(limit=limit) if hasattr(self, '_search_query'): keywords = SearchableEntity._FullTextIndex(self._search_query) for keyword in keywords: filter = pb.add_filter() filter.set_op(datastore_pb.Query_Filter.EQUAL) prop = filter.add_property() prop.set_name(SearchableEntity._FULL_TEXT_INDEX_PROPERTY) prop.mutable_value().set_stringvalue(keyword) return pb
def _comparison(self, op, value): if op != '=': raise datastore_errors.BadFilterError( 'StructuredProperty filter can only use ==') # Import late to avoid circular imports. from ndb.query import FilterNode, ConjunctionNode, PostFilterNode value = self.Validate(value) # None is not allowed! filters = [] for name, prop in value._properties.iteritems(): val = prop.RetrieveValue(value) if val is not None: filters.append(FilterNode(self._name + '.' + name, op, val)) if not filters: raise datastore_errors.BadFilterError( 'StructuredProperty filter without any values') if len(filters) == 1: return filters[0] filters.append(PostFilterNode(self._filter_func, value)) return ConjunctionNode(filters)
def search(self, search_query, properties=ALL_PROPERTIES): """Adds a full text search to this query. Args: search_query, a string containing the full text search query. Returns: self """ self._search_query = search_query self._properties = properties if self._properties not in getattr(self, '_searchable_properties', [ALL_PROPERTIES]): raise datastore_errors.BadFilterError( '%s does not have a corresponding index. Please add it to' 'the SEARCHABLE_PROPERTIES list' % self._properties) return self