【问题标题】:NDB, Querying across multiple models. AppEngineNDB,跨多个模型查询。应用引擎
【发布时间】:2014-01-09 17:06:15
【问题描述】:

我正在努力跨多个模型进行查询。 这是我的类结构的样子:

class User(ndb.Model):
    ...

class LogVisit(ndb.Model)
    user = ndb.KeyProperty(kind=User)
    ...

class LogOnline(ndb.Model)
    logVisit = ndb.KeyProperty(kind = LogVisit)
    ...

我想获取用户的 LogOnline 列表

我想做的是这样的:

qry = LogOnline.query(LogOnline.logvisit.get().user.get() == user)

但是应用引擎不允许我在查询中使用 get 方法。

对解决此问题的最佳方法有什么想法吗? 非常感谢。

【问题讨论】:

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


    【解决方案1】:

    最有效的方法是将用户的密钥存储在 LogOnline 实体中。我们无法看到模型的其余部分,无法看到 LogVisit 为整个练习添加了什么,因此很难看到 LogVisit 作为中间实体为设计带来了什么。

    那么就

     LogOnline.query().filter(LogOnline.user == user)
    

    如果您想在 appengine 上拥有可扩展的应用程序,您将不得不停止思考 SQL。考虑纯粹的实体关系,不要试图规范化数据模型。像 LogVisit 这样的中间实体往往只在您需要多对多关系时使用,但如果您有多个用于特定关系的实例,则仍然效率低下。

    【讨论】:

    • 谢谢。如您所见,我来自关系数据库背景。在其中我尝试通过规范化所有内容来停止数据重复。
    • 将用户当前的 LogOnline 密钥存储在用户实体中是否也是一个想法?或者这在代码重复方面被认为是糟糕的设计?每次创建新的 LogOnline 时都必须更新 User 实体。但是,它将允许更简单的查询来找出用户当前正在使用的 LogOnline。你怎么看?
    • 不,必须写入用户实体会非常低效。只需将用户密钥存储在 LogOnLine 中即可为您提供所需的查询。您应该尽量减少写入。他们的成本。
    【解决方案2】:

    你做错了。

    # user variable is assumed to be a key
    logonlines = [] # You can use set also
    logvisits = LogVisit.query().filter(LogVisit.user == user).fetch()
    for logvisit in logvisits:
        logOnlinesA = LogOnline.query().filter(LogOnline.logVisit == logvisit.key).fetch()
        logonlines.extend(logOnlinesA)
    

    试一试:

    logvisits = LogVisit.query().filter(LogVisit.user == user).fetch(keys_only=True)
    logOnlinesA = LogOnline.query().filter(LogOnline.logVisit.in(logvisits)).fetch()
    

    【讨论】:

    • 谢谢。这是实现这一目标的最简单方法吗?我原以为我可以用一个查询完成整个操作?
    • 在每个用户都有大量 LogVisits 的系统中,这可能会开始变得非常低效。
    • 您正在尝试根据关系数据库来设计您的应用程序。 Google NDB Datastore 更像是一个 noSql 数据库。
    • 您在上面提供的代码会产生语法错误。我也尝试过 logOnlinesA = LogOnline.query().filter(LogOnline.logVisit in logvisits ).fetch() 但这会产生“TypeError: Cannot filter a non-Node argument;”
    • logOnlinesA = LogOnline.query().filter(LogOnline.logVisit.in(*logvisits)).fetch()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-03
    相关资源
    最近更新 更多