thirdparty/google_appengine/google/appengine/ext/search/__init__.py
author Pawel Solyga <Pawel.Solyga@gmail.com>
Sun, 06 Sep 2009 23:31:53 +0200
changeset 2864 2e0b0af889be
parent 2309 be1b94099f2d
permissions -rwxr-xr-x
Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
     1
#!/usr/bin/env python
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
     2
#
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
     3
# Copyright 2007 Google Inc.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
     4
#
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
     5
# Licensed under the Apache License, Version 2.0 (the "License");
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
     6
# you may not use this file except in compliance with the License.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
     7
# You may obtain a copy of the License at
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
     8
#
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
     9
#     http://www.apache.org/licenses/LICENSE-2.0
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    10
#
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    11
# Unless required by applicable law or agreed to in writing, software
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    12
# distributed under the License is distributed on an "AS IS" BASIS,
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    13
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    14
# See the License for the specific language governing permissions and
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    15
# limitations under the License.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    16
#
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    17
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    18
"""Full text indexing and search, implemented in pure python.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    19
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    20
Defines a SearchableModel subclass of db.Model that supports full text
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    21
indexing and search, based on the datastore's existing indexes.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    22
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    23
Don't expect too much. First, there's no ranking, which is a killer drawback.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    24
There's also no exact phrase match, substring match, boolean operators,
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    25
stemming, or other common full text search features. Finally, support for stop
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    26
words (common words that are not indexed) is currently limited to English.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    27
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    28
To be indexed, entities must be created and saved as SearchableModel
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    29
instances, e.g.:
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    30
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    31
  class Article(search.SearchableModel):
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    32
    text = db.TextProperty()
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    33
    ...
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    34
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    35
  article = Article(text=...)
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    36
  article.save()
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    37
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    38
To search the full text index, use the SearchableModel.all() method to get an
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    39
instance of SearchableModel.Query, which subclasses db.Query. Use its search()
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    40
method to provide a search query, in addition to any other filters or sort
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    41
orders, e.g.:
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    42
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    43
  query = article.all().search('a search query').filter(...).order(...)
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    44
  for result in query:
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    45
    ...
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    46
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    47
The full text index is stored in a property named __searchable_text_index.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    48
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    49
Specifying multiple indexes and properties to index
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    50
---------------------------------------------------
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    51
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    52
By default, one index is created with all string properties. You can define
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    53
multiple indexes and specify which properties should be indexed for each by
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    54
overriding SearchableProperties() method of model.SearchableModel, for example:
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    55
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    56
  class Article(search.SearchableModel):
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    57
    @classmethod
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    58
    def SearchableProperties(cls):
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    59
      return [['book', 'author'], ['book']]
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    60
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    61
In this example, two indexes will be maintained - one that includes 'book' and
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    62
'author' properties, and another one for 'book' property only. They will be
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    63
stored in properties named __searchable_text_index_book_author and
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    64
__searchable_text_index_book respectively. Note that the index that includes
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    65
all properties will not be created unless added explicitly like this:
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    66
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    67
  @classmethod
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    68
  def SearchableProperties(cls):
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    69
    return [['book', 'author'], ['book'], search.ALL_PROPERTIES]
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    70
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    71
The default return value of SearchableProperties() is [search.ALL_PROPERTIES]
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    72
(one index, all properties).
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    73
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    74
To search using a custom-defined index, pass its definition
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    75
in 'properties' parameter of 'search':
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    76
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    77
  Article.all().search('Lem', properties=['book', 'author'])
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    78
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    79
Note that the order of properties in the list matters.
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    80
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    81
Adding indexes to  index.yaml
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    82
-----------------------------
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    83
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    84
In general, if you just want to provide full text search, you *don't* need to
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    85
add any extra indexes to your index.yaml. However, if you want to use search()
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    86
in a query *in addition to* an ancestor, filter, or sort order, you'll need to
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    87
create an index in index.yaml with the __searchable_text_index property. For
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    88
example:
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    89
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    90
  - kind: Article
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    91
    properties:
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    92
    - name: __searchable_text_index
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    93
    - name: date
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    94
      direction: desc
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    95
    ...
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    96
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    97
Similarly, if you created a custom index (see above), use the name of the
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    98
property it's stored in, e.g. __searchable_text_index_book_author.
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
    99
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   100
Note that using SearchableModel will noticeable increase the latency of save()
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   101
operations, since it writes an index row for each indexable word. This also
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   102
means that the latency of save() will increase roughly with the size of the
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   103
properties in a given entity. Caveat hacker!
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   104
"""
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   105
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   106
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   107
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   108
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   109
import re
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   110
import string
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   111
import sys
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   112
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   113
from google.appengine.api import datastore
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   114
from google.appengine.api import datastore_errors
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   115
from google.appengine.api import datastore_types
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   116
from google.appengine.ext import db
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   117
from google.appengine.datastore import datastore_pb
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   118
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   119
ALL_PROPERTIES = []
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   120
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   121
class SearchableEntity(datastore.Entity):
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   122
  """A subclass of datastore.Entity that supports full text indexing.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   123
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   124
  Automatically indexes all string and Text properties, using the datastore's
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   125
  built-in per-property indices. To search, use the SearchableQuery class and
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   126
  its Search() method.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   127
  """
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   128
  _FULL_TEXT_INDEX_PROPERTY = '__searchable_text_index'
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   129
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   130
  _FULL_TEXT_MIN_LENGTH = 3
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   131
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   132
  _FULL_TEXT_STOP_WORDS = frozenset([
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   133
   'a', 'about', 'according', 'accordingly', 'affected', 'affecting', 'after',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   134
   'again', 'against', 'all', 'almost', 'already', 'also', 'although',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   135
   'always', 'am', 'among', 'an', 'and', 'any', 'anyone', 'apparently', 'are',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   136
   'arise', 'as', 'aside', 'at', 'away', 'be', 'became', 'because', 'become',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   137
   'becomes', 'been', 'before', 'being', 'between', 'both', 'briefly', 'but',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   138
   'by', 'came', 'can', 'cannot', 'certain', 'certainly', 'could', 'did', 'do',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   139
   'does', 'done', 'during', 'each', 'either', 'else', 'etc', 'ever', 'every',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   140
   'following', 'for', 'found', 'from', 'further', 'gave', 'gets', 'give',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   141
   'given', 'giving', 'gone', 'got', 'had', 'hardly', 'has', 'have', 'having',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   142
   'here', 'how', 'however', 'i', 'if', 'in', 'into', 'is', 'it', 'itself',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   143
   'just', 'keep', 'kept', 'knowledge', 'largely', 'like', 'made', 'mainly',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   144
   'make', 'many', 'might', 'more', 'most', 'mostly', 'much', 'must', 'nearly',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   145
   'necessarily', 'neither', 'next', 'no', 'none', 'nor', 'normally', 'not',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   146
   'noted', 'now', 'obtain', 'obtained', 'of', 'often', 'on', 'only', 'or',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   147
   'other', 'our', 'out', 'owing', 'particularly', 'past', 'perhaps', 'please',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   148
   'poorly', 'possible', 'possibly', 'potentially', 'predominantly', 'present',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   149
   'previously', 'primarily', 'probably', 'prompt', 'promptly', 'put',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   150
   'quickly', 'quite', 'rather', 'readily', 'really', 'recently', 'regarding',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   151
   'regardless', 'relatively', 'respectively', 'resulted', 'resulting',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   152
   'results', 'said', 'same', 'seem', 'seen', 'several', 'shall', 'should',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   153
   'show', 'showed', 'shown', 'shows', 'significantly', 'similar', 'similarly',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   154
   'since', 'slightly', 'so', 'some', 'sometime', 'somewhat', 'soon',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   155
   'specifically', 'state', 'states', 'strongly', 'substantially',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   156
   'successfully', 'such', 'sufficiently', 'than', 'that', 'the', 'their',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   157
   'theirs', 'them', 'then', 'there', 'therefore', 'these', 'they', 'this',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   158
   'those', 'though', 'through', 'throughout', 'to', 'too', 'toward', 'under',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   159
   'unless', 'until', 'up', 'upon', 'use', 'used', 'usefully', 'usefulness',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   160
   'using', 'usually', 'various', 'very', 'was', 'we', 'were', 'what', 'when',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   161
   'where', 'whether', 'which', 'while', 'who', 'whose', 'why', 'widely',
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   162
   'will', 'with', 'within', 'without', 'would', 'yet', 'you'])
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   163
297
35211afcd563 Load /Users/solydzajs/Downloads/google_appengine/ into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 149
diff changeset
   164
  _word_delimiter_regex = re.compile('[' + re.escape(string.punctuation) + ']')
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   165
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   166
  _searchable_properties = [ALL_PROPERTIES]
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   167
297
35211afcd563 Load /Users/solydzajs/Downloads/google_appengine/ into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 149
diff changeset
   168
  def __init__(self, kind_or_entity, word_delimiter_regex=None, *args,
35211afcd563 Load /Users/solydzajs/Downloads/google_appengine/ into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 149
diff changeset
   169
               **kwargs):
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   170
    """Constructor. May be called as a copy constructor.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   171
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   172
    If kind_or_entity is a datastore.Entity, copies it into this Entity.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   173
    datastore.Get() and Query() returns instances of datastore.Entity, so this
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   174
    is useful for converting them back to SearchableEntity so that they'll be
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   175
    indexed when they're stored back in the datastore.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   176
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   177
    Otherwise, passes through the positional and keyword args to the
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   178
    datastore.Entity constructor.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   179
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   180
    Args:
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   181
      kind_or_entity: string or datastore.Entity
297
35211afcd563 Load /Users/solydzajs/Downloads/google_appengine/ into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 149
diff changeset
   182
      word_delimiter_regex: a regex matching characters that delimit words
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   183
    """
297
35211afcd563 Load /Users/solydzajs/Downloads/google_appengine/ into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 149
diff changeset
   184
    self._word_delimiter_regex = word_delimiter_regex
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   185
    if isinstance(kind_or_entity, datastore.Entity):
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   186
      self._Entity__key = kind_or_entity._Entity__key
2309
be1b94099f2d Update Google App Engine to 1.2.2 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 1278
diff changeset
   187
      self._Entity__unindexed_properties = frozenset(kind_or_entity.unindexed_properties())
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   188
      if isinstance(kind_or_entity, SearchableEntity):
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   189
        if getattr(kind_or_entity, '_searchable_properties', None) is not None:
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   190
          self._searchable_properties = kind_or_entity._searchable_properties
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   191
      self.update(kind_or_entity)
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   192
    else:
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   193
      super(SearchableEntity, self).__init__(kind_or_entity, *args, **kwargs)
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   194
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   195
  def _ToPb(self):
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   196
    """Rebuilds the full text index, then delegates to the superclass.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   197
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   198
    Returns:
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   199
      entity_pb.Entity
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   200
    """
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   201
    for properties_to_index in self._searchable_properties:
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   202
      index_property_name = SearchableEntity.IndexPropertyName(properties_to_index)
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   203
      if index_property_name in self:
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   204
        del self[index_property_name]
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   205
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   206
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   207
      if not properties_to_index:
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   208
        properties_to_index = self.keys()
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   209
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   210
      index = set()
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   211
      for name in properties_to_index:
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   212
        if not self.has_key(name):
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   213
          continue
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   214
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   215
        values = self[name]
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   216
        if not isinstance(values, list):
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   217
          values = [values]
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   218
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   219
        if (isinstance(values[0], basestring) and
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   220
            not isinstance(values[0], datastore_types.Blob)):
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   221
          for value in values:
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   222
            index.update(SearchableEntity._FullTextIndex(
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   223
                value, self._word_delimiter_regex))
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   224
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   225
      index_list = list(index)
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   226
      if index_list:
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   227
        self[index_property_name] = index_list
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   228
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   229
    return super(SearchableEntity, self)._ToPb()
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   230
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   231
  @classmethod
297
35211afcd563 Load /Users/solydzajs/Downloads/google_appengine/ into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 149
diff changeset
   232
  def _FullTextIndex(cls, text, word_delimiter_regex=None):
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   233
    """Returns a set of keywords appropriate for full text indexing.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   234
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   235
    See SearchableQuery.Search() for details.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   236
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   237
    Args:
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   238
      text: string
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   239
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   240
    Returns:
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   241
      set of strings
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   242
    """
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   243
297
35211afcd563 Load /Users/solydzajs/Downloads/google_appengine/ into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 149
diff changeset
   244
    if word_delimiter_regex is None:
35211afcd563 Load /Users/solydzajs/Downloads/google_appengine/ into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 149
diff changeset
   245
      word_delimiter_regex = cls._word_delimiter_regex
35211afcd563 Load /Users/solydzajs/Downloads/google_appengine/ into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 149
diff changeset
   246
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   247
    if text:
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   248
      datastore_types.ValidateString(text, 'text', max_len=sys.maxint)
297
35211afcd563 Load /Users/solydzajs/Downloads/google_appengine/ into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 149
diff changeset
   249
      text = word_delimiter_regex.sub(' ', text)
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   250
      words = text.lower().split()
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   251
149
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents: 109
diff changeset
   252
      words = set(unicode(w) for w in words)
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   253
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   254
      words -= cls._FULL_TEXT_STOP_WORDS
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   255
      for word in list(words):
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   256
        if len(word) < cls._FULL_TEXT_MIN_LENGTH:
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   257
          words.remove(word)
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   258
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   259
    else:
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   260
      words = set()
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   261
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   262
    return words
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   263
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   264
  @classmethod
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   265
  def IndexPropertyName(cls, properties):
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   266
    """Given index definition, returns the name of the property to put it in."""
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   267
    name = SearchableEntity._FULL_TEXT_INDEX_PROPERTY
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   268
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   269
    if properties:
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   270
      name += '_' + '_'.join(properties)
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   271
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   272
    return name
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   273
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   274
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   275
class SearchableQuery(datastore.Query):
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   276
  """A subclass of datastore.Query that supports full text search.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   277
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   278
  Only searches over entities that were created and stored using the
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   279
  SearchableEntity or SearchableModel classes.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   280
  """
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   281
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   282
  def Search(self, search_query, word_delimiter_regex=None,
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   283
             properties=ALL_PROPERTIES):
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   284
    """Add a search query. This may be combined with filters.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   285
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   286
    Note that keywords in the search query will be silently dropped if they
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   287
    are stop words or too short, ie if they wouldn't be indexed.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   288
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   289
    Args:
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   290
     search_query: string
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   291
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   292
    Returns:
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   293
      # this query
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   294
      SearchableQuery
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   295
    """
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   296
    datastore_types.ValidateString(search_query, 'search query')
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   297
    self._search_query = search_query
297
35211afcd563 Load /Users/solydzajs/Downloads/google_appengine/ into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 149
diff changeset
   298
    self._word_delimiter_regex = word_delimiter_regex
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   299
    self._properties = properties
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   300
    return self
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   301
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   302
  def _ToPb(self, *args, **kwds):
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   303
    """Adds filters for the search query, then delegates to the superclass.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   304
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   305
    Mimics Query._ToPb()'s signature. Raises BadFilterError if a filter on the
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   306
    index property already exists.
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   307
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   308
    Returns:
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   309
      datastore_pb.Query
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   310
    """
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   311
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   312
    properties = getattr(self, "_properties", ALL_PROPERTIES)
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   313
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   314
    index_property_name = SearchableEntity.IndexPropertyName(properties)
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   315
    if index_property_name in self:
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   316
      raise datastore_errors.BadFilterError(
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   317
        '%s is a reserved name.' % index_property_name)
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   318
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   319
    pb = super(SearchableQuery, self)._ToPb(*args, **kwds)
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   320
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   321
    if hasattr(self, '_search_query'):
297
35211afcd563 Load /Users/solydzajs/Downloads/google_appengine/ into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 149
diff changeset
   322
      keywords = SearchableEntity._FullTextIndex(
35211afcd563 Load /Users/solydzajs/Downloads/google_appengine/ into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 149
diff changeset
   323
          self._search_query, self._word_delimiter_regex)
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   324
      for keyword in keywords:
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   325
        filter = pb.add_filter()
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   326
        filter.set_op(datastore_pb.Query_Filter.EQUAL)
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   327
        prop = filter.add_property()
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   328
        prop.set_name(index_property_name)
1278
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   329
        prop.set_multiple(len(keywords) > 1)
149
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents: 109
diff changeset
   330
        prop.mutable_value().set_stringvalue(unicode(keyword).encode('utf-8'))
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   331
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   332
    return pb
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   333
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   334
1278
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   335
class SearchableMultiQuery(datastore.MultiQuery):
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   336
  """A multiquery that supports Search() by searching subqueries."""
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   337
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   338
  def Search(self, *args, **kwargs):
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   339
    """Add a search query, by trying to add it to all subqueries.
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   340
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   341
    Args:
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   342
      args: Passed to Search on each subquery.
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   343
      kwargs: Passed to Search on each subquery.
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   344
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   345
    Returns:
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   346
      self for consistency with SearchableQuery.
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   347
    """
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   348
    for q in self:
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   349
      q.Search(*args, **kwargs)
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   350
    return self
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   351
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   352
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   353
class SearchableModel(db.Model):
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   354
  """A subclass of db.Model that supports full text search and indexing.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   355
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   356
  Automatically indexes all string-based properties. To search, use the all()
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   357
  method to get a SearchableModel.Query, then use its search() method.
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   358
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   359
  Override SearchableProperties() to define properties to index and/or multiple
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   360
  indexes (see the file's comment).
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   361
  """
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   362
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   363
  @classmethod
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   364
  def SearchableProperties(cls):
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   365
    return [ALL_PROPERTIES]
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   366
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   367
  class Query(db.Query):
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   368
    """A subclass of db.Query that supports full text search."""
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   369
    _search_query = None
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   370
    _properties = None
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   371
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   372
    def search(self, search_query, properties=ALL_PROPERTIES):
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   373
      """Adds a full text search to this query.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   374
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   375
      Args:
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   376
        search_query, a string containing the full text search query.
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   377
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   378
      Returns:
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   379
        self
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   380
      """
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   381
      self._search_query = search_query
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   382
      self._properties = properties
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   383
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   384
      if self._properties not in getattr(self, '_searchable_properties', [ALL_PROPERTIES]):
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   385
        raise datastore_errors.BadFilterError(
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   386
          '%s does not have a corresponding index. Please add it to'
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   387
          'the SEARCHABLE_PROPERTIES list' % self._properties)
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   388
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   389
      return self
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   390
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   391
    def _get_query(self):
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   392
      """Wraps db.Query._get_query() and injects SearchableQuery."""
1278
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   393
      query = db.Query._get_query(self,
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   394
                                  _query_class=SearchableQuery,
a7766286a7be Load /Users/solydzajs/Downloads/google_appengine into
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 297
diff changeset
   395
                                  _multi_query_class=SearchableMultiQuery)
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   396
      if self._search_query:
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   397
        query.Search(self._search_query, properties=self._properties)
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   398
      return query
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   399
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   400
  def _populate_internal_entity(self):
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   401
    """Wraps db.Model._populate_internal_entity() and injects
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   402
    SearchableEntity."""
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   403
    entity = db.Model._populate_internal_entity(self,
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   404
                                                _entity_class=SearchableEntity)
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   405
    entity._searchable_properties = self.SearchableProperties()
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   406
    return entity
109
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   407
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   408
  @classmethod
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   409
  def from_entity(cls, entity):
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   410
    """Wraps db.Model.from_entity() and injects SearchableEntity."""
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   411
    if not isinstance(entity, SearchableEntity):
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   412
      entity = SearchableEntity(entity)
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   413
    return super(SearchableModel, cls).from_entity(entity)
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   414
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   415
  @classmethod
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   416
  def all(cls):
620f9b141567 Load ../../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   417
    """Returns a SearchableModel.Query for this kind."""
2864
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   418
    query = SearchableModel.Query(cls)
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   419
    query._searchable_properties = cls.SearchableProperties()
2e0b0af889be Update Google App Engine from 1.2.3 to 1.2.5 in thirdparty folder.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2309
diff changeset
   420
    return query