Javascript 解析:追随者上的复合查询超时

Javascript 解析:追随者上的复合查询超时,javascript,android,parse-platform,inner-query,Javascript,Android,Parse Platform,Inner Query,我有一个活动表,上面写着哪些用户关注谁。(fromUser和toUser) 我正在构建一个排行榜,看看在追随者中谁的评分最高 所以我创建了这个查询: ParseQuery<ParseObject> queryActivityFollowing = new ParseQuery<>("Activity"); queryActivityFollowing.whereEqualTo("type", "follow"); queryActivityFollowing.whereE

我有一个活动表,上面写着哪些用户关注谁。(
fromUser
toUser
) 我正在构建一个排行榜,看看在追随者中谁的评分最高

所以我创建了这个查询:

ParseQuery<ParseObject> queryActivityFollowing = new ParseQuery<>("Activity");
queryActivityFollowing.whereEqualTo("type", "follow");
queryActivityFollowing.whereEqualTo("fromUser", ParseUser.getCurrentUser());
queryActivityFollowing.setLimit(500);

// innerQuery, only get Users posted by the users I follow
ParseQuery<ParseUser> queryUserFollowing = ParseUser.getQuery();
queryUserFollowing.whereMatchesQuery("toUser", queryActivityFollowing);

// querySelf
ParseQuery<ParseUser> querySelf = ParseUser.getQuery();
querySelf.whereEqualTo("objectId", ParseUser.getCurrentUser().getObjectId());

List<ParseQuery<ParseUser>> queries = new ArrayList<>();
queries.add(queryUserFollowing);
queries.add(querySelf);

query = ParseQuery.or(queries);
query.orderByDescending("rating_count");
query.setLimit(20);
ParseQuery查询活动follow=new ParseQuery(“活动”);
查询活动如下。whereEqualTo(“类型”、“后续”);
queryActivityFollowing.whereEqualTo(“fromUser”,ParseUser.getCurrentUser());
查询活动如下。设置限制(500);
//innerQuery,仅获取我跟踪的用户发布的用户
ParseQuery queryUserFollowing=ParseUser.getQuery();
queryUserFollowing.whereMatchesQuery(“toUser”,queryActivityFollowing);
//自责
ParseQuery querySelf=ParseUser.getQuery();
querySelf.whereEqualTo(“objectId”,ParseUser.getCurrentUser().getObjectId());
列表查询=新建ArrayList();
querys.add(queryUserFollowing);
查询。添加(查询您自己);
query=ParseQuery.or(查询);
query.orderByDescending(“评级计数”);
查询.设定限额(20);
但不知何故,它会超时,并且永远不会显示结果。 我的查询是否有效率低下的地方

谢谢

编辑: 数据说明:
Activity
是一个包含3列的类,
fromUser
toUser
type
fromUser
toUser
是指向
\u User
类的指针,
type
是一个字符串

\u User
中,我有经典属性和一个名为
rating\u count
的整数,它是orderBy条件(上面更新的代码)


实际上,我认为查询没有超时,只返回0个结果。我关注我的一些用户,因此它肯定不是预期的输出。

这是一个困难的问题,因为parse的查询只支持最低限度的这类内容。我能提供的最好的想法是:

  • 对活动表
    whereEqualTo(“type”,“follow”)
    whereEqualTo(“fromUser”,ParseUser.getCurrentUser())的一个查询
  • 不要抱怨,不要抱怨你自己。这些都是不必要的。这也将您从
    Parse.Query.or()
    中解放出来
  • setLimit(1000)
    将在下面解释原因
  • include(“toUser”)
  • 完成后,循环遍历结果,最大化for
    result.get(“toUser”).getInt(“rating\u count”)
    ,因为结果将是活动的实例,您将急切地获取它们相关的toUser
  • 此方案比您编写的方案更简单,可以完成任务。然而,可能的一个主要问题是,它将丢失超过1000个追随者的用户的数据。如果这是个问题,请告诉我,我可以建议一个更复杂的答案。一个小缺点是,您将被迫自己在内存中进行搜索(可能是排序),以查找最大的分级计数

    编辑-对于>1k关注者,您必须多次调用查询,将
    跳过
    设置为上一次查询中接收到的记录数,并将结果收集到一个大数组中

    您关于传输如此多数据的观点得到了很好的理解,您可以通过将所有这些都放到云函数中,在云中执行内存工作,并且只返回客户端需要的记录,来最大限度地减少网络使用。(这种方法还有一个额外的好处,就是用javascript编写代码,我比java说得更流利,所以我可以更规范地编写代码)

    编辑2-在云代码中执行此操作的好处是将网络流量减少到只有那些具有最高评级的用户(例如,20个)。它不能解决我前面提到的其他问题。下面是我在云端的做法

    var _ = require('underscore');
    
    Parse.Cloud.define("topFollowers", function(request, response) {
        var user = new Parse.User({id:request.params.userId});
        topFollowers(user, 20).then(function(result) {
            response.success(result);
        }, function(error) {
            response.error(error);
        });
    });
    
    // return the top n users who are the top-rated followers of the passed user
    function topFollowers(user, n) {
        var query = new Parse.Query("Activity");
        query.equalTo("type", "follow");
        query.equalTo("fromUser", user);
        query.include("toUser");
        return runQuery(query).then(function(results) {
            var allFollowers = _.map(results, function(result) { return result.get("toUser"); });
            var sortedFollowers = _.sortBy(allFollowers, function(user) { return user.get("rating_count"); });
            return _.first(sortedFollowers, n);
        });
    }
    
    // run and rerun a query using skip until all results are gathered in results array
    function runQuery(query, results) {
        results = results || [];
        query.skip(results.length);
        return query.find().then(function(nextResults) {
            results = results.concat(nextResults);
            return (nextResults.length)? runQuery(query, results) : results;
        });
    }
    

    注意-我没有测试过这一点,但在生产中也有类似的工作。

    如果您想要更改数据模型,那么有一个解决方案可以满足您的需要,还有一些附带的好处。考虑一个系统,其中用户类只与应用程序和真人之间的关系有关。用户之间的公共面由一个新类(称为PublicUser或Persona)表示

    在这个
    PublicUser
    类中,您有一个指向拥有它的
    user
    的指针,还有一个指向其他
    PublicUser
    的指针数组,该用户是
    后面的
    用户。此类还包含
    评级
    属性。现在OP中的查询很简单:

  • 查询PublicUser,其中key“following”等于currentUser
  • 按等级排序,限制在20或您希望限制的任何数字

  • 就这样。该方案的另一个优点是访问控制。系统理解,PublicUser中的任何内容对其他PublicUser都是可读的,关于u_____________________________________。在问题中有一些关于相关类和属性的提示,但请包括它们的类型(例如,fromUser是指向_用户的指针?)以及它们的含义(例如,fromUser遵循toUser或其他方式?)。我看不到任何对“评级”属性的引用,文本指出该属性可能很重要。@dahn:谢谢你的评论,我已经更新了这个问题。如果我遵循userB,那么fromUser包含我的指针,而tuser包含userBHi@Danh的指针,这似乎会起作用,但我认为还有另一个低效之处。我必须通过网络获取1000个用户(有点贵),然后对他们进行排序,选出前20名。(极端情况,但你明白我的意思)。要确保所有的处理和计算都在Parse端完成,还有什么更复杂的答案呢?我想我可以删除查询本身,在获取追随者的结果时添加
    getCurrentUser()
    ,看看它是否在前20名之间。对你第二个更复杂的答案仍感兴趣根本问题是我们真正想要的是对toUser进行排序