且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在Google App Engine中获得我的某个模特的独特价值

更新时间:2023-02-16 16:39:03

Datastore无法在单个查询中为您执行此操作。数据存储请求总是从索引返回连续的结果块,并且索引始终由给定类型的所有实体组成,并根据指定的任何顺序进行排序。查询只是因为一个字段具有重复值而无法跳过项目。



一种选择是重构数据。例如引入代表区域的新实体类型。在添加教程时,如果尚未存在相应的区域,则创建相应的区域,如果没有教程保留在相同的区域中,则删除相应的区域。如果每个区域在该区域存储了一系列教程,这可能不会太繁琐(尽管保持事务与事务的一致性等实际上相当复杂)。我希望实体的关键字可以基于区域字符串本身,这意味着您始终可以执行关键字查询而不是查询来获取区域实体。

另一个选项是使用排队的任务或cron作业定期创建所有区域的列表,并根据需要将其累积在多个请求上,并将结果放在数据存储区或memcache中。这当然意味着这些区域列表可能会暂时过时(或者如果有不断变化的话,它可能永远不会完全在日期中),这可能会或可能不会被您接受。

最后,如果与教程相比可能只有很少的区域,可以通过请求第一个教程(按区域排序),然后请求第一个教程的区域是大于第一个的面积,依此类推。但是这需要每个不同区域的请求,所以不可能很快。

I have a model, below, and I would like to get all the distinct area values. The SQL equivalent is select distinct area from tutorials

class Tutorials(db.Model):  
    path = db.StringProperty()
    area = db.StringProperty()
    sub_area = db.StringProperty()
    title = db.StringProperty()
    content = db.BlobProperty()
    rating = db.RatingProperty()
    publishedDate = db.DateTimeProperty()
    published = db.BooleanProperty()

I know that in Python I can do

    a = ['google.com', 'livejournal.com', 'livejournal.com', 'google.com', '***.com']
 b = set(a)
    b
    >>> set(['livejournal.com', 'google.com', '***.com'])

But that would require me moving the area items out of the query into another list and then running set against the list (sounds very inefficient) and if I have a distinct item that is in position 1001 in the datastore I wouldnt see it because of the fetch limit of 1000.

I would like to get all the distinct values of area in my datastore to dump it to the screen as links.

Datastore cannot do this for you in a single query. A datastore request always returns a consecutive block of results from an index, and an index always consists of all the entities of a given type, sorted according to whatever orders are specified. There's no way for the query to skip items just because one field has duplicate values.

One option is to restructure your data. For example introduce a new entity type representing an "area". On adding a Tutorial you create the corresponding "area" if it doesn't already exist, and on deleting a Tutoral delete the corresponding "area" if no Tutorials remain with the same "area". If each area stored a count of Tutorials in that area, this might not be too onerous (although keeping things consistent with transactions etc would actually be quite fiddly). I expect that the entity's key could be based on the area string itself, meaning that you can always do key lookups rather than queries to get area entities.

Another option is to use a queued task or cron job to periodically create a list of all areas, accumulating it over multiple requests if need be, and put the results either in the datastore or in memcache. That would of course mean the list of areas might be temporarily out of date at times (or if there are constant changes, it might never be entirely in date), which may or may not be acceptable to you.

Finally, if there are likely to be very few areas compared with tutorials, you could do it on the fly by requesting the first Tutorial (sorted by area), then requesting the first Tutorial whose area is greater than the area of the first, and so on. But this requires one request per distinct area, so is unlikely to be fast.