【问题标题】:AppEngine datastore 'ends with' queryAppEngine 数据存储区“以”查询结尾
【发布时间】:2014-02-25 12:01:31
【问题描述】:

关于这个答案:https://stackoverflow.com/a/1554837/1135424 我发现“starts with”可以使用以下方式完成:

MyModel.all().filter('prop >=', prefix).filter('prop <', prefix + u'\ufffd')

它提到要执行“ends with”查询需要存储字符串的反转,然后应用与上述相同的策略。

例如,如果我当前的数据是域字符串,例如:

domains | reverse_domain
------- | --------------
.com.io | oi.moc.
.com.eu | ue.moc.
.com.mx | xm.moc.

如果我想查询以 '.io' 结尾的域,我应该这样做:

suffix = '.io'
MyModel.all().filter(
    'reverse_domain >=', suffix).filter(
    'reserve_domain <', suffix + u'\ufffd')

但是在测试时,在 python 命令行上进行字符串比较我得到了这个:

>>> '.com.io'[::-1] >= '.io'
True
>>> '.com.io'[::-1] < '.io' +  u'\ufffd'
False

改变顺序,首先是u'\ufffd',然后是后缀

>>> '.com.io'[::-1] < u'\ufffd' + '.io'
True

所以想知道在执行 'ends with' 时,除了颠倒存储数据的顺序之外,u'\ufffd' 是否应该先行,就像这样:

MyModel.all().filter(
    'reverse_prop >=', suffix).filter(
    'reverse_prop <', u'\ufffd' + suffix)

datastore filter 是否遵循与 python 在比较字符串时相同的字典顺序?

基本上怎么做:

SELECT domain FROM domains WHERE <domain name> LIKE CONCAT('%', domain)

例如,如果我搜索 google.com.io,我可以得到域“.com.io”,那么,如何获取以某事结尾的现有域/字符串?

更新

虽然测试似乎我只需要将运算符 >= 更改为 ,这给了我 LIKE '%string'

suffix = '.io'[::-1]
MyModel.all().filter(
    'reverse_domain <=', suffix).filter(
    'reserve_domain <', suffix + u'\ufffd')

如果我想搜索一个字符串是否以我已有的记录结尾:

>>> assert('.com.io'[::-1] <= '.com.io'[::-1] and '.com.io'[::-1] < '.com.io'[::-1] + u'\ufffd')

>>> assert('.com.io'[::-1] <= 'google.com.io'[::-1] and '.com.io'[::-1] < 'google.com.io'[::-1] + u'\ufffd') 

>>> assert('.com.io'[::-1] <= 'gle.com.io'[::-1] and '.com.io'[::-1] < 'gle.com.io'[::-1] + u'\ufffd')

【问题讨论】:

  • 你必须在搜索它之前反转后缀,因为索引中的文本也被反转了。
  • 你的意思是'.com.io'[::-1] &gt;= '.io'[::-1]'.com.io'[::-1] &lt; '.io'[::-1] + u'\ufffd'
  • 对。您实际上只是在反向列上进行前缀搜索,因此您想使用与startswith“相同的技术”来搜索“oi”。
  • 我做了一些测试,除了反转后缀和数据之外,我似乎还必须将&gt;= 运算符更改为&lt;=

标签: python google-app-engine python-2.7 google-cloud-datastore


【解决方案1】:

如果您的用例涉及搜索顶级域,我建议将 URL 拆分为两个单独的属性。这将使查找具有给定 TLD 的所有记录变得容易,并为其他搜索提供更大的灵活性。

如果您有数百万条记录,您也可以考虑使用整数来表示每个 TLD。它将减少数据的大小。

当您使用单个相等过滤器而不是两个不等过滤器时,这种方法也可能会更快一些。

【讨论】:

  • 您的意思是拆分域,例如 ['google','com','io'] 并从左到右搜索 io.com.google 直到找到匹配项?
  • 我的意思是使用两个单独的属性 - 一个用于“google”,另一个用于“com.io”。
  • 可能,我应该将当前数据拆分为每个顶级域等等。
  • 我不知道您的要求,但您也可以使用“com.io”和其他 TLD 作为单独的实体类型。如果您从不搜索所有域,这是一个不错的选择。
  • 可能是,但也可能为“io”创建一个实体,为“com”创建另一个实体,并以域结尾,如果我需要搜索特定域,我只会搜索他们的父母而是像 IP->COM->gogole 对吗?
猜你喜欢
  • 1970-01-01
  • 2015-04-16
  • 1970-01-01
  • 2012-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多