0

问题:用户(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.

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

提前致谢!

4

2 回答 2

0

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

于 2013-02-11T18:10:58.300 回答
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是key。这个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 中获取计数为 3 的 UserAs(因为我们要匹配 3 个标签列表:行业、年龄组和标签)。

上述代码示例中可能存在一些语法错误,尤其是对于键和对象的使用;并且在某些情况下使用了伪代码。我只是想概述一下解决方案。希望这可以帮助。随时分享任何评论。

于 2013-02-11T20:19:44.333 回答