当把更新应用程序到到 1.8.4 版本后,开始遇到一个错误,在 1.8.1 版本中工作正常的代码,现在在尝试将文档添加到搜索索引时却失败了。具体错误信息如下:
Traceback (most recent call last):
File "~/tools/devappserver2/api_server.py", line 62, in _handle_POST
api_response = _execute_request(request).Encode()
File "~/tools/devappserver2/api_server.py", line 123, in _execute_request
make_request()
File "~/tools/devappserver2/api_server.py", line 115, in make_request
request_id)
File "~/google/appengine/api/apiproxy_stub.py", line 130, in MakeSyncCall
method(request, response)
File "~/google/appengine/api/search/simple_search_stub.py", line 654, in _Dynamic_IndexDocument
index.IndexDocuments(params.document_list(), response)
File "~/google/appengine/api/search/simple_search_stub.py", line 404, in IndexDocuments
self._inverted_index.AddDocument(doc_id, document)
File "~/google/appengine/api/search/simple_search_stub.py", line 303, in AddDocument
self._AddFieldType(field.name(), field.value().type())
File "~/google/appengine/api/search/simple_search_stub.py", line 289, in _AddFieldType
self._schema.AddFieldType(name, field_type)
AttributeError: 'dict' object has no attribute 'AddFieldType'
ERROR 2013-09-14 22:31:45,132 webapp2.py:1552] AttributeError("'dict' object has no attribute 'AddFieldType'",)
Traceback (most recent call last):
File "~/lib/webapp2-2.5.2/webapp2.py", line 1535, in __call__
rv = self.handle_exception(request, response, e)
File "~/lib/webapp2-2.5.2/webapp2.py", line 1529, in __call__
rv = self.router.dispatch(request, response)
File "~/lib/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "~/lib/webapp2-2.5.2/webapp2.py", line 1102, in __call__
return handler.dispatch()
File "~/lib/webapp2-2.5.2/webapp2.py", line 572, in dispatch
return self.handle_exception(e, self.app.debug)
File "~/lib/webapp2-2.5.2/webapp2.py", line 570, in dispatch
return method(*args, **kwargs)
File "~/docroot/update.py", line 49, in get
booking.add_to_search_index()
File "~/docroot/booking.py", line 94, in add_to_search_index
index.put(booking_full_text_document)
File "~/google/appengine/api/search/search.py", line 2506, in put
response)
File "~/google/appengine/api/apiproxy_stub_map.py", line 94, in MakeSyncCall
return stubmap.MakeSyncCall(service, call, request, response)
File "~/google/appengine/api/apiproxy_stub_map.py", line 328, in MakeSyncCall
rpc.CheckSuccess()
File "~/google/appengine/api/apiproxy_rpc.py", line 156, in _WaitImpl
self.request, self.response)
File "~/google/appengine/ext/remote_api/remote_api_stub.py", line 200, in MakeSyncCall
self._MakeRealSyncCall(service, call, request, response)
File "~/google/appengine/ext/remote_api/remote_api_stub.py", line 234, in _MakeRealSyncCall
raise pickle.loads(response_pb.exception())
RuntimeError: AttributeError("'dict' object has no attribute 'AddFieldType'",)
INFO 2013-09-14 22:31:45,145 module.py:593] default: "GET /update/somekey/someparamter/value HTTP/1.1" 500 2691
2、解决方案
发现从 1.8.1 版本升级到 1.8.4 版本可能会导致此问题。解决办法是:
使用 google.appengine.ext.ndb 而不是 google.appengine.api.datastore 来管理你的数据。
from google.appengine.ext import ndb
使用 google.appengine.api.search 而不是 google.appengine.api.search.simple_search 来操作你的搜索索引。
from google.appengine.api import search
如果你的代码中使用了 google.appengine.api.search.simple_search,则需要将其替换为 google.appengine.api.search。
# 旧版本
from google.appengine.api.search.simple_search import Document
# 新版本
from google.appengine.api.search import Document
确保你的 Document 对象的字段类型与你的搜索索引中定义的字段类型相匹配。可以使用 Document.fields 属性来获取 Document 对象的字段类型。
# 旧版本
from google.appengine.api.search.simple_search import TextField
# 新版本
from google.appengine.api.search import TextField
# 旧版本
document = Document(fields=[TextField(name='field1', value='value1')])
# 新版本
document = Document(fields=[TextField(name='field1', value='value1')])
将 Document 对象添加到你的搜索索引中。可以使用 Index.put() 方法来实现。
index = search.Index(name="fullText")
index.put(document)
代码示例:
from google.appengine.ext import ndb
from google.appengine.api import search
import logging
class Booking(ndb.Model):
timestamp = ndb.DateTimeProperty(auto_now_add=True)
last_modified = ndb.DateTimeProperty(auto_now=True)
field1 = ndb.StringProperty()
field2 = ndb.StringProperty()
#etc...
def add_to_search_index(self):
list_of_full_text_fields = [
'field1',
'field2',
]
full_text_data = []
for field in list_of_full_text_fields:
full_text_data.append(unicode(getattr(self, field)))
full_text_data = ' '.join(full_text_data)
full_text_document = search.Document(
doc_id = self.key.urlsafe(),
fields=[
search.TextField(
name='f',
value=full_text_data
),
]
)
try:
index = search.Index(name="fullText")
index.put(full_text_document)
except search.Error:
logging.exception('Put failed')
注意:确保你已将你的应用程序升级到 App Engine 1.8.4 或更高版本。