“黄沙中,飞舞着我们的先王,他们在空中俯视着子民们对蓝色的向往。” 火之章 霜之章 [最新更新:9月15日]

你在这里看到的是一位.NET程序员的执着及其信仰的效率世界观。我们行走在消逝中,但我们都有希望,都有传承。

GoogleAppsEngine中GQL里出现中文字符串时的解决方案 ,2008-11-18,0条评论

在上一篇文章《GoogleAppsEngine数据存储中的中文编码支持问题》中提到过储存数据的时候的一下编码问题,这里有必要再补充一下,搜索数据的时候遇到的编码问题更多。而且错误隐藏得更深。


在SQL中,我们可以这样写:SELECT * FROM TABLE1 WHERE name = "str1",这时只要TABLE1的name字段中存在有值为"str1"的字符串,就肯定可以得到1条或者多条结果。
但是在GQL中情况就不这么乐观了。明明存在str1的值,但是就是搜不出来。搞了一个上午,终于发现是因为编码问题造成的:

如果你的name字段将来要在WHERE子句中出现,那么就老老实实用最稳定的ascii码保存数据进去。并且数据类型必须是db.StringProperty(),因为db.TextProperty()不支持搜索。保存进去的时候,最好是能够强制再转换一遍编码(不管以前有没有转换过,在提交数据的最后关头再做一遍可以得到最大的安全保证),提交的时候是ascii码,查询的时候也必须是ascii码。

下面是局部例子:

__name = "strname"
temp.name = __name
temp.put() #提交


result = temp.sql("WHERE name = :1",__name) #查找

在上面的行为中千万不要包含任何u、unicode()、encode等之类的动作,否则到时候就会出现数据明明存在就是查找不出的情况。
经过错误消息提示跟踪,同时发现了一个新的问题:GQL数据库内部是以纯ascii码来进行查找动作的,也就是说只要在WHERE子句中出现任何双字节的字符,不管你编码是否正确,都会出错。这也就是说如果我们要写“WHERE XXX = '中文字符'”是不可能的了,在某些情况下,我们必须查找中文,怎么办?我正好因为这个问题作了个不得已的方案:使用MD5来加密字段值,保存在一个新的字段中,因为MD5的唯一性和以及它的值是定长的32位字母,我们就查找的时候就查找这个MD5字段就行了。就当前情况来看,这一点冗余代价是必须付出的。这些并不是python的问题,而是GQL数据库的问题,所以各位也没有必要再去查找python的中文支持办法了。

总结:如果某个字段在将来需要对它进行查询,记住3个要点
1 存储的时候以ascii码存储,
2 查找的时候以ascii码查找。
3 如果需要保存中文,必须建立一个新的字段来存储MD5值。
3点缺一不可。

本文具有一定的时效性,描述的这些问题和解决方案发生于2008年11月,将来有可能Google会在GAE的升级中提供更好的兼容性。
mcts

Category

Tag

Archives

  • kvspas
  • Powered by Google App Engine