上一篇 [擒猿筆記篇] Android 利用 Parse Cloud Server (一) ParseObject 介紹了 ParseObject 的用法,但是目前一次只能上傳或抓取一筆資料,那如果要同時處理多筆資料要怎麼辦?此時就得用到 ParseQuery 了。
基本用法
以下作法可以從雲端資料庫中取回所有 ParseObject 的 List
ParseQuery<ParseObject> query = ParseQuery.getQuery("GameScore");
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> scoreList, ParseException e) {
if (e == null) {
Log.d("score", "Retrieved " + scoreList.size() + " scores");
} else {
Log.d("score", "Error: " + e.getMessage());
}
}
});
條件篩選
可以在 findInBackground 之前對 ParseQuery 物件加上篩選條件,如:
query.whereEqualTo("playerName", "Dan Stemkoski");
也可以限制回傳的結果筆數,如:
query.setLimit(10); // limit to at most 10 results
若只需要一筆資料,可以使用 getFirst() 或 getFirstBackground(),如:
ParseQuery<ParseObject> query = ParseQuery.getQuery("GameScore");
query.whereEqualTo("playerEmail", "dstemkoski@example.com");
query.getFirstInBackground(new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
if (object == null) {
Log.d("score", "The getFirst request failed.");
} else {
Log.d("score", "Retrieved the object.");
}
}
});
也可以用 setSkip() 來忽略查詢結果的前幾筆資料:
query.setSkip(10); // skip the first 10 results
也可以設定依據某個欄位的值來做排序,如:
// Sorts the results in ascending order by the score field query.orderByAscending("score"); // Sorts the results in descending order by the score field query.orderByDescending("score");
承上,還可以增加複合欄位排序篩選,如:
// Sorts the results in ascending order by the score field // if the previous sort keys are equal. query.addAscendingOrder("playerAge"); // Sorts the results in descending order by the score field // if the previous sort keys are equal. query.addDescendingOrder("playerAge");
也可以有邏輯條件判斷式,如:
// Restricts to wins < 50 query.whereLessThan("wins", 50); // Restricts to wins <= 50 query.whereLessThanOrEqualTo("wins", 50); // Restricts to wins > 50 query.whereGreaterThan("wins", 50); // Restricts to wins >= 50 query.whereGreaterThanOrEqualTo("wins", 50);
如果要篩選出符合或不符合多組關鍵字的資料,可以採取以下寫法:
String[] names = {"Jonathan Walsh", "Dario Wunsch", "Shawn Simon"}; query.whereContainedIn("playerName", Arrays.asList(names)); query.whereNotContainedIn("playerName", Arrays.asList(names));
如果要篩選有無特定欄位的資料,可以採取以下寫法:
// Finds objects that have the score set query.whereExists("score"); // Finds objects that don't have the score set query.whereDoesNotExist("score");
跨 Table 做複合篩選也是行地,以下寫法可以對從第一個 Table 取得的資料再做一次篩選:
ParseQuery<ParseQuery> teamQuery = ParseQuery.getQuery("Team");
teamQuery.whereGreaterThan("winPct", 0.5);
ParseQuery<ParseQuery> userQuery = ParseQuery.getQuery("_User");
userQuery.whereMatchesKeyInQuery("hometown", "city", teamQuery);
userQuery.findInBackground(new FindCallback<ParseUser>() {
void done(List<ParseUser> results, ParseException e) {
// results has the list of users with a hometown team with a winning record
}
});
承上,也可以取得與上例相反的資料:
ParseQuery<ParseQuery> losingUserQuery = ParseQuery.getQuery("_User");
losingUserQuery.whereDoesNotMatchKeyInQuery("hometown", "city", teamQuery);
losingUserQuery.findInBackground(new FindCallback<ParseUser>() {
void done(List<ParseUser> results, ParseException e) {
// results has the list of users with a hometown team with a losing record
}
});
此外,也可以只篩選特定欄位的資料,如以下寫法:
ParseQuery<ParseObject> query = ParseQuery.getQuery("GameScore");
query.selectKeys(Arrays.asList("playerName", "score"));;
List<ParseObject> results = query.find();
其餘欄位可以用以下方法,需要時再抓取:
ParseObject object = results.get(0);
object.fetchIfNeededInBackground(new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
// all fields of the object will now be available here.
}
});
篩選 Array Values
假設雲端資料庫上有一個欄位叫做 "arrayKey" 儲存的值為 Array Values,可透過以下方式來取得 arrayKey 中含有特定數值的資料:
// Find objects where the array in arrayKey contains the number 2.
query.whereEqualTo("arrayKey", 2);
進階用法如下,可一次篩選出含有多筆條件的資料:
// Find objects where the array in arrayKey contains all of the numbers 2, 3, and 4.
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(2);
numbers.add(3);
numbers.add(4);
query.whereContainsAll("arrayKey", numbers);
篩選 String Values
透過以下方式可篩選出指定欄位中開頭有特定字串的資料:
// Finds barbecue sauces that start with 'Big Daddy's'.
ParseQuery<ParseObject> query = ParseQuery.getQuery("BarbecueSauce");
query.whereStartsWith("name", "Big Daddy's");
關聯式篩選
以下寫法可以將另一組 ParseObject 當成篩選條件,篩選出跟這個 ParseObject 有關的:
// Assume ParseObject myPost was previously created.
ParseQuery<ParseObject> query = ParseQuery.getQuery("Comment");
query.whereEqualTo("post", myPost);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> commentList, ParseException e) {
// commentList now has the comments for myPost
}
});
以下寫法可以從前一次篩選出的結果中做關聯式篩選的動作:
ParseQuery<ParseObject> innerQuery = ParseQuery.getQuery("Post");
innerQuery.whereExists("image");
ParseQuery<ParseObject> query = ParseQuery.getQuery("Comment");
query.whereMatchesQuery("post", innerQuery);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> commentList, ParseException e) {
// comments now contains the comments for posts with images.
}
});
承上,以下寫法可以取得與上相反的資料:
ParseQuery<ParseObject> query = ParseQuery.getQuery("Comment");
query.whereDoesNotMatchQuery("post", innerQuery);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> commentList, ParseException e) {
// comments now contains the comments for posts without images.
}
});
此外,可以在篩選時偷渡其他 Table 的資料 XD
ParseQuery<ParseObject> query = ParseQuery.getQuery("Comment"); // Retrieve the most recent ones query.orderByDescending("createdAt"); // Only retrieve the last ten query.setLimit(10); // Include the post data with each comment query.include("post"); query.findInBackground(new FindCallback<ParseObject>() { public void done(List<ParseObject> commentList, ParseException e) { // commentList now contains the last ten comments, and the "post" // field has been populated. For example: for (ParseObject comment : commentList) { // This does not require a network access. ParseObject post = comment.getParseObject("post"); Log.d("post", "retrieved a related post"); } } });
從 Local DataStore 篩選資料
若有開啟 Local DataStore 的話,也可以用以下方式從 Local DataStore 篩選資料出來:
query.fromLocalDatastore();
query.findInBackground(new FindCallback<ParseObject>() {
public void done(final List<ParseObject> scoreList, ParseException e) {
if (e == null) {
// Results were successfully found from the local datastore.
} else {
// There was an error.
}
}
});
篩選方式跟先前一模一樣,篩選結果會包含所有被 pin 過的 ParseObject。
將篩選結果做快取
可以將篩選的結果做快取,儲存在 Lcoal Datastore,如此一來可以加快存取速度,如下寫法:
final String TOP_SCORES_LABEL = "topScores"; // Query for the latest objects from Parse. query.findInBackground(new FindCallback<ParseObject>() { public void done(final List<ParseObject> scoreList, ParseException e) { if (e != null) { // There was an error or the network wasn't available. return; } // Release any objects previously pinned for this query. ParseObject.unpinAllInBackground(TOP_SCORES_LABEL, scoreList, new DeleteCallback() { public void done(ParseException e) { if (e != null) { // There was some error. return; } // Add the latest results for this query to the cache. ParseObject.pinAllInBackground(TOP_SCORES_LABEL, scoreList); } }); } });
如果沒有開啟 Local DataStore 也沒關係,還有以下方式可以做快取:
query.setCachePolicy(ParseQuery.CachePolicy.NETWORK_ELSE_CACHE); query.findInBackground(new FindCallback<ParseObject>() { public void done(List<ParseObject> scoreList, ParseException e) { if (e == null) { // Results were successfully found, looking first on the // network and then on disk. } else { // The network was inaccessible and we have no cached data // for this query. } } });
其中 cache policy 的類型與各代表意義如下:
- IGNORE_CACHE:此次篩選不做快取
- CACHE_ONLY:此次篩選只從快取中抓資料,不透過網路
- NETWORK_ONLY: 此次篩選只從網路抓資料,不透過快取
- CACHE_ELSE_NETWORK:此次篩選先從快取抓資料,沒有資料再透過網路
- NETWORK_ELSE_CACHE:此次篩選先從網路抓資料,沒有資料再透過快取
- CACHE_THEN_NETWORK:此次篩選先從快取抓資料,然後再透過網路抓一次
Parse 還提供了以下方法對快取做操作:
// Check to see if there is a cached result for the query with: boolean isInCache = query.hasCachedResult(); // Remove any cached results for a query with: query.clearCachedResult(); // Remove cached results for all queries with: ParseQuery.clearAllCachedResults();
計數
以下方式可以得到此次符合篩選結果的資料筆數:
ParseQuery<ParseObject> query = ParseQuery.getQuery("GameScore");
query.whereEqualTo("playerName", "Sean Plott");
query.countInBackground(new CountCallback() {
public void done(int count, ParseException e) {
if (e == null) {
// The count request succeeded. Log the count
Log.d("score", "Sean has played " + count + " games");
} else {
// The request failed
}
}
});
複合式篩選
若要從多個篩選條件得到只要符合其中一個條件的結果,可以利用以下寫法:
ParseQuery<ParseObject> lotsOfWins = ParseQuery.getQuery("Player");
lotsOfWins.whereGreaterThan(150);
ParseQuery<ParseObject> fewWins = ParseQuery.getQuery("Player");
fewWins.whereLessThan(5);
List<ParseQuery<ParseObject>> queries = new ArrayList<ParseQuery<ParseObject>>();
queries.add(lotsOfWins);
queries.add(fewWins);
ParseQuery<ParseObject> mainQuery = ParseQuery.or(queries);
mainQuery.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> results, ParseException e) {
// results has the list of players that win a lot or haven't won much.
}
});
幹你娘我累壞了...
您好,我想请教一个问题,我想通过findinbackground 进行一个查询 把查询结果 显示在listview上,其中我需要显示的一项数据,需要进行一次计数工作,也就是用到 countinbackground 然而 这个countinbackground 总是在findinbackground 执行完后再执行,是的我的计数内容无法显示在listview上,请问有什么解决方法?
回覆刪除