我有一个活动表,其中列出了哪些用户关注谁。 (fromUsertoUser
我正在构建一个排行榜,以查看在关注者中谁获得的评分最高。

所以我创建了这个查询:

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);


但是以某种方式,它超时并且从不显示结果。
我的查询效率低下吗?

谢谢!

编辑:
资料说明:
Activity是具有3列的类,分别为fromUsertoUsertypefromUsertoUser是指向_User类的指针,type是字符串

_User中,我具有经典属性,还有一个名为rating_count的整数,该整数是orderBy条件(上面的更新代码)。

实际上,我认为查询不会超时,而只会返回0个结果。我关注一些用户,因此绝对不是预期的输出。

最佳答案

这是一个艰难的过程,因为parse的查询仅极少支持这种事情。我能提供的最好的主意是:


在活动表whereEqualTo("type", "follow")whereEqualTo("fromUser", ParseUser.getCurrentUser())上的一个查询
没有queryUserFollowing,没有querySelf。这些都是不必要的。这也将您从Parse.Query.or()中解放出来。
setLimit(1000)将在下面解释原因
include("toUser")
完成后,遍历结果,为result.get("toUser").getInt("rating_count")最大化,因为结果将是Activity的实例,并且您将急切地获取它们的与user相关的信息。


该方案比您编写的方案简单,并且可以完成工作。但是,可能的主要问题是它将丢失具有1000个关注者的用户的数据。让我知道是否有问题,我可以提出一个更复杂的答案。一个小的缺点是,您将被迫在内存中自己进行搜索(可能是某种排序)以找到最大的rating_count。

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

您传输大量数据的观点已得到很好的理解,您可以通过将所有这些都放入云功能,在云中进行内存中工作并仅返回客户端所需的记录来最大程度地减少网络使用。 (这种方法的另一个好处是用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;
    });
}


注意-我还没有测试过,但是在生产中也有类似的东西。

09-25 17:31
查看更多