21

我一直在使用 Parse 来检索列表视图的数据。不幸的是,默认情况下,他们将请求限制为 100,最大为 1000。我班上的人数超过了 1000 人。我在网上找到了一个链接,它显示了在 iOS 上执行此操作的方法,但您将如何在 Android 上执行此操作?网页链接

我目前正在循环中将所有数据添加到数组列表中,直到所有项目都完成(100)然后将它们添加到列表中

4

11 回答 11

45

我已经想出了如何实现我的目标:

声明全局变量

private static List<ParseObject>allObjects = new ArrayList<ParseObject>();

创建查询

final ParseQuery parseQuery = new ParseQuery("Objects");
parseQuery.setLimit(1000);
parseQuery.findInBackground(getAllObjects());

查询回调

int skip=0;
FindCallback getAllObjects(){
    return new FindCallback(){
        public void done(List<ParseObject> objects, ParseException e) {
            if (e == null) {

                allObjects.addAll(objects);
                 int limit =1000;
                if (objects.size() == limit){
                    skip = skip + limit;
                    ParseQuery query = new ParseQuery("Objects");
                    query.setSkip(skip);
                    query.setLimit(limit);
                    query.findInBackground(getAllObjects());
                }
                //We have a full PokeDex
                else {
                    //USE FULL DATA AS INTENDED
                }
        }
    };
}
于 2013-09-09T10:39:18.037 回答
14

这是一个没有承诺的JavaScript版本..

这些是全局变量(不需要集合,只是我的一个坏习惯)..

   ///create a collection of cool things and instantiate it (globally)
    var CoolCollection = Parse.Collection.extend({
       model: CoolThing
    }), coolCollection = new CoolCollection();

这是获得结果的“循环”功能..

//recursive call, initial loopCount is 0 (we haven't looped yet)
function getAllRecords(loopCount){

    ///set your record limit
    var limit = 1000;

    ///create your eggstra-special query
     new Parse.Query(CoolThings)
            .limit(limit)
            .skip(limit * loopCount) //<-important
            .find({
             success: function (results) {
                 if(results.length > 0){

                     //we do stuff in here like "add items to a collection of cool things"
                     for(var j=0; j < results.length; j++){
                         coolCollection.add(results[j]);
                     }

                     loopCount++; //<--increment our loop because we are not done

                     getAllRecords(loopCount); //<--recurse
                 }
                 else
                 {
                     //our query has run out of steam, this else{} will be called one time only
                     coolCollection.each(function(coolThing){
                        //do something awesome with each of your cool things
                     });
                 }
            },
             error: function (error) {
                //badness with the find
             }
         });
}

这就是你所说的(或者你可以用其他方式):

getAllRecords(0);
于 2014-09-11T00:46:41.377 回答
4

JAVA

因此,在 5 年 4 个月后,@SquiresSquire 的上述答案需要进行一些更改才能使其对我有用,我想与您分享。

private static List<ParseObject>allObjects = new ArrayList<ParseObject>();
ParseQuery<ParseObject> parseQuery = new ParseQuery<ParseObject>("CLASSNAME");
parseQuery.setLimit(1000);
parseQuery.findInBackground(getAllObjects());
FindCallback <ParseObject> getAllObjects() {
    return new FindCallback <ParseObject>() {
        @Override
        public void done(List<ParseObject> objects, ParseException e) {
            if (e == null) {
                allObjects.addAll(objects);
                int limit = 1000;
                if (objects.size() == limit) {
                    skip = skip + limit;
                    ParseQuery query = new ParseQuery("CLASSNAME");
                    query.setSkip(skip);
                    query.setLimit(limit);
                    query.findInBackground(getAllObjects());
                }
                //We have a full PokeDex
                else {
                    //USE FULL DATA AS INTENDED
                }
            }
        }
    
    };
于 2018-11-10T21:34:47.933 回答
3

C#中,我使用此递归:

private static async Task GetAll(int count = 0, int limit = 1000)
{
    if (count * limit != list.Count) return;
    var res = await ParseObject.GetQuery("Row").Limit(limit).Skip(list.Count).FindAsync();
    res.ToList().ForEach(x => list.Add(x));
    await GetAll(++count);
}

JS版本:

function getAll(list) {
    new Parse.Query(Row).limit(1000).skip(list.length).find().then(function (result) {
        list = list.concat(result);
        if (result.length != 1000) {
            //do here something with the list...
            return;
        }

        getAll(list);
    });
}

用法:GetAll()在 C# 和getAll([])JS 中。

Row我将类中的所有行存储在list. 在每个请求中,我得到 1000 行并跳过list. 当当前导出的行数与预期不同时,递归停止。

于 2016-01-28T11:59:59.090 回答
3

重要如果您使用的是 开源解析服务器,那么这里的所有答案都没有用,默认情况下它会限制 100 行,但您可以 在查询中输入任何值,limit(100000) //WORKS 不需要递归 调用,只需将限制设置为你想要的行数

https://github.com/parse-community/parse-server/issues/5383

于 2020-03-27T13:30:07.667 回答
3

**编辑:下面的答案是多余的,因为开源解析服务器对要获取的最大行数没有任何限制

 //instead of var result = await query.find();
    query.limit(99999999999);//Any value greater then max rows you want
    var result = await query.find();**

原答案:

Javascript/云代码

这是一种适用于所有查询的干净方法

async function fetchAllIgnoringLimit(query,result) {
  const limit = 1000;
  query.limit(limit);
  query.skip(result.length);

  const results = await query.find();
  result = result.concat(results)

  if(results.length === limit) {
    return await fetchAllIgnoringLimit(query,result );
  } else {
    return result;
  }

}

这是如何使用它

var GameScore = Parse.Object.extend("GameScore");
var query = new Parse.Query(GameScore);
//instead of var result = await query.find();
var result = await fetchAllIgnoringLimit(query,new Array());
console.log("got "+result.length+" rows")
于 2020-02-19T07:49:44.873 回答
1

一个Swift 3示例:

var users    = [String] ()
var payments = [String] ()
///set your record limit
let limit = 29
//recursive call, initial loopCount is 0 (we haven't looped yet)
func loadAllPaymentDetails(_ loopCount:  Int){
    ///create your NEW eggstra-special query
    let paymentsQuery  = Payments.query()
    paymentsQuery?.limit = limit
    paymentsQuery?.skip  = limit*loopCount
    paymentsQuery?.findObjectsInBackground(block: { (objects, error) in
        if let objects = objects {
            //print(#file.getClass(),"  ",#function,"  loopcount: ",loopCount,"      #ReturnedObjects: ",  objects.count)
            if objects.count > 0 {
                //print(#function, " no. of objects :", objects.count)
                for paymentsObject in objects {
                    let user   = paymentsObject[Utils.name] as! String
                    let amount = paymentsObject[Utils.amount] as! String
                    self.users.append(user)
                    self.payments.append(amount)
                }
                //recurse our loop with increment because we are not done
                self.loadAllPaymentDetails(loopCount + 1); //<--recurse
            }else {
                //our query has run out of steam, this else{} will be called one time only
                //if the Table had been initially empty, lets inform the user:
                if self.users.count == 1 {
                    Utils.createAlert(self, title: "No Payment has been made yet", message: "Please Encourage Users to make some Payments", buttonTitle: "Ok")
                }else {
                    self.tableView.reloadData()
                }
            }
        }else if error != nil {
            print(error!)
        }else {
            print("Unknown Error")
        }
    })
}

改编自上面@deLux_247 的示例。

于 2017-07-31T21:48:53.520 回答
1

YAS(又一个解决方案!)在javascriptasync()中使用和。await()

async parseFetchAll(collected = []) {
  let query = new Parse.Query(GameScore);
  const limit = 1000;

  query.limit(limit);
  query.skip(collected.length);

  const results = await query.find();

  if(results.length === limit) {
    return await parseFetchAll([ ...collected, ...results ]);
  } else {
    return collected.concat(results);
  }

}
于 2017-07-05T23:30:59.047 回答
0

您可以使用 CloudCode 实现此目的...创建一个您可以调用的自定义函数,该函数将枚举整个集合并从中构建响应,但更明智的选择是对您的请求进行分页,并获取 1000 条(甚至更少)的记录一次,根据需要将它们动态添加到您的列表中。

于 2013-06-24T07:06:58.447 回答
0

这是我的 C# .NET 解决方案

 List<ParseObject> allObjects = new List<ParseObject>();
 ParseQuery<ParseObject> query1 = ParseObject.GetQuery("Class");
 int totalctr = await query1.CountAsync()
 for (int i = 0; i <= totalctr / 1000; i++)
 {
     ParseQuery<ParseObject> query2 = ParseObject.GetQuery("Class").Skip(i * 1000).Limit(1000);
     IEnumerable<ParseObject> ibatch = await query2.FindAsync();
     allObjects.AddRange(ibatch);
 }
于 2021-01-20T07:05:52.793 回答
0

SWIFT 4 的通用版本:

警告:这未经测试!

尝试调整 nyxee 的答案以适用于任何查询:

func getAllRecords(for query: PFQuery<PFObject>, then doThis: @escaping (_ objects: [PFObject]?, _ error: Error?)->Void) {
    let limit = 1000
    var objectArray : [PFObject] = []
    query.limit = limit
    func recursiveQuery(_ loopCount:  Int = 0){
        query.skip  = limit * loopCount
        query.findObjectsInBackground(block: { (objects, error) in
            if let objects = objects {
                objectArray.append(contentsOf: objects)
                if objects.count == limit {
                    recursiveQuery(loopCount + 1)
                } else {
                    doThis(objectArray, error)
                }
            } else {
                doThis(objects, error)
            }
        })
    }
    recursiveQuery()
}
于 2020-05-18T11:04:30.373 回答