具有长对象列表的对象作为具有端点 - 原型数据存储的字段

时间:2014-10-26 18:00:34

标签: google-app-engine google-cloud-endpoints endpoints-proto-datastore

我要为Club建模members User类型class User(EndpointsModel): username = ndb.StringProperty(required=True) class Club(EndpointsModel): .... members_key = ndb.KeyProperty(kind="User", repeated=True) @EndpointsAliasProperty(repeated=True,property_type=User.ProtoModel()) def members(self): return ndb.get_multi(self.members_key) 。显然俱乐部可能会有很多会员。

我已经完成了这个

ProtoCollection()

在回复中我这样做了整个用户列表,在这种情况下,我有5000名会员需要一段时间。

是否有可能将此列表分页?可能使用ProtoModel()代替/club/{id}/members? (我尝试没有成功)。

或者,我如何创建{{1}}类型的端点,让我返回成员列表(分页)?

2 个答案:

答案 0 :(得分:1)

我在这里。我做了一些测试,我发现了这个解决方案(方法是club/{id}/members

我为标准端点创建了一个资源容器。这些消息会复制query_method作为输入的内容。

ID_RESOURCE_PAGE = endpoints.ResourceContainer(
    message_types.VoidMessage,
    id=messages.IntegerField(1, variant=messages.Variant.INT64),
    cursor=messages.StringField(2, variant=messages.Variant.STRING, required=False, default="1"),
    limit=messages.IntegerField(3, variant=messages.Variant.INT32, required=False, default=10)
)

然后我创建了一个像这样的标准@endopint.method

@endpoints.method(ID_RESOURCE_PAGE, User.ProtoCollection(),
                      path='club/{id}/members',
                      http_method='GET',
                      name='club.members')
    def club_memebers(self, request):
        # check if user has ownership
        club = Club.get_by_id(request.id)
        page_size = request.limit
        # convert the cursors, usually it's a token, here is page number.
        page = int(request.cursor)
        # internal check, just in case.
        if (page is None or page < 0):
            raise endpoints.BadRequestException(message="Page field must be a positive integer")
        if (page_size is None or page_size < 0 or page > 100):
            raise endpoints.BadRequestException(
                message="Page_size field must be a positive integer and cannot be greater than 100")
        # compute start and end users to retrive
        start = (page - 1) * page_size
        end = page * page_size
        # crop the list
        res_list = club.membersUser[start:end]
        # create the object
        ret = User.ToMessageCollection(res_list)
        # it's probably another page
        if (len(res_list) == page_size):
            # add next page as nextPageToken, not the best but the easy way
            ret.nextPageToken = str(page + 1)
        return ret

要注意我使用User.ProtoCollection()自动序列化集合,并将页码伪造成ret.nextPageToken。最后一次编辑看起来不太干净(实际上并非如此),但查询有效。

尽管如此,我对此解决方案并不满意。

答案 1 :(得分:1)

还有很多其他方法可以实现多用户对一个俱乐部的关系 - 我想过存储一个&#34;俱乐部&#34;用户中重复的属性,引用他们所属的俱乐部(存储俱乐部的密钥)。您查询满足俱乐部属性的用户,并将结果限制为页面大小。使用类似

的模式

next_page_results = User.all().filter('club =', club_key).filter('__key__ >', last_seen_key).order('key').run(limit=page_size)

确保正确检索页面,在正确的位置开始和停止

(其中last_seen_key = next_page_results[-1]用于下次通话)

您执行此操作的方式,每次都会获取所有结果并在内存中进行过滤。这很糟糕,而且会花钱。