得到错误"无法满足查询 - 太多IN /!=值"。怎么解决这个?

时间:2013-02-11 05:47:47

标签: python google-app-engine

问题:用户(B)需要基于某些标准从一组用户(A)获得帮助。用户(A)在其个人资料中设置此标准。

class UsersAProfiles(db.Model):
    industries = db.StringListProperty()  #technology, etc. (total 20)
    agegroups  = db.StringListProperty()  #teenagers, etc. (total 10)
    tags       = db.StringListProperty()  #cooking, etc.
    (while each User A can enter at most 10 tags, but there is no limit on 
     what tags are used, e.g., sql, gym, etc. (limited by dictionary!)
    ...                                   #there are many other properties

用户(B)设置单独存储的标准

class UserBRequestForHelp(db.Model):
    myindustries = db.StringListProperty()  #technology, etc. (<20)
    myagegroups  = db.StringListProperty()  #teenagers, etc. (<10)
    mytags       = db.StringListProperty()  #cooking, etc.
    ...                                     #there are many other properties

现在我需要所有可能帮助B的用户A的列表。为此,我尝试运行以下查询:

query = db.GqlQuery("SELECT * FROM UsersAProfiles WHERE 
        industries IN :1 AND 
        agegroups  IN :2 AND
        tags       IN :3", 
        userB_obj.myindustries , userB_obj.myagegroups, userB_obj.mytags)

但是我收到以下错误:

  Cannot satisfy query -- too many IN/!= values.

我真的被困在这里,不知道如何解决这个问题。如何运行此类查询。此外,我是否需要以不同方式设计模型类,以便我可以运行此类查询?如果是,请有人帮忙。

提前感谢!

2 个答案:

答案 0 :(得分:0)

当您使用IN创建查询时,GAE必须将该查询分解为多个“index = value”子查询,执行每个子查询并收集组合它们的结果,就像它们是一次搜索一样。查询可以扩展到的子查询数量有限制,that limit is 30。如果您正在使用31个子查询创建查询,那么这将解释您遇到此问题的原因。换句话说,你的情况是len(userB_obj.myindustries)+ len(userB_obj.myagegroups)+ len(userB_obj.mytags)&gt; 30。

答案 1 :(得分:0)

对于上述问题,以下方法可能有用。

  1. 在单独的模型中列出TAGS,其中列出了所有匹配的UserA配置文件。

    class TAGS(db.Model):
        UserAIds  = db.StringListProperty() 
    

    在上面,每个标签都是关键。 (标签=技术,青少年,烹饪等)

  2. 当用户B设置条件,然后找到匹配的用户A时,我们可以运行的查询如下:

    i = 0
    for industry in userB_obj.myindustries:
          t1_obj[i] = TAGS.get_by_key_name(industry)
          i = i + 1
    

    (在上面的t1_obj [i]中,您有具有匹配行业的用户A个人资料列表)

    j = 0
    for agegroup in userB_obj.myagegroups:
          t2_obj[j] = TAGS.get_by_key_name(agegroup)
          j = j + 1
    

    (在上面的t2_obj [j]中,您有具有匹配年龄组的用户A个人资料列表)

    k = 0
    for tag in userB_obj.mytags:
          t3_obj[k] = TAGS.get_by_key_name(tag)
          k = k + 1
    

    (在上面的t3_obj [k]中,您有具有匹配标签的用户A个人资料列表)

  3. 接下来,您需要做的就是找到所有三个中存在的UserA配置文件,即t1_obj,t2_obj,t3_obj,这就是全部! 现在找到上面所有3中出现的UserA配置文件,不确定是否有可以执行此操作的python函数。但是,使用模型实例,您可以按如下方式解决它

    class MatchingUserAs(db.Model):
          count  = db.IntegerProperty(default=0) 
          source = db.StringProperty(default=None)
    

    (在上面的模型类中,UserA id是键。此UserAids存储在t1_key [i] .UserAIds,t2_key [j] .UserAids,t3_key [k] .UserAIds)

  4. 现在,遍历t1_obj [i],t2_obj [j],t3_obj [k]并在MatchingUserAs中插入UserA id,并在每次插入行/更新行时将计数递增1。

    <"loop through t1_obj[i]">:
          Matchkey = MatchingUserAs.get_or_insert(t1_obj[i].UserAId)
          Matchkey.count = 1
          Matchkey.source = 'industry'
          Matchkey.put()
    
    <"loop through t2_obj[j]">:
          Matchkey = MatchingUserAs.get_or_insert(t2_obj[j].UserAId)
          #the following if check has been added to avoid incrementing the counter
          #when same UserAid is present in, say, t2_obj[0], and t2_obj[1], etc.
          if(Matchkey.source != 'agegroup')
              Matchkey.count  = Matchkey.count + 1
              Matchkey.source = 'agegroup'
          Matchkey.put()
    
    <"loop through t3_obj[j]">:
          Matchkey = MatchingUserAs.get_or_insert(t3_obj[j].UserAId)
          if(Matchkey.source != 'tags')
              Matchkey.count  = Matchkey.count + 1
              Matchkey.source = 'tags'
          Matchkey.put()
    
  5. 现在,您需要做的就是从MatchingUserAs获取那些UserAs,其数量为3(因为我们要匹配3个标记列表:行业,年龄组和标签)。

  6. 上面的代码示例中可能存在一些语法错误,特别是对于密钥和对象的使用;在某些情况下,使用了伪代码。我只是想概述解决方案。希望这可以帮助。随意分享任何意见。