Introduction
The Parse platform provides a complete backend solution for your mobile application. Our goal is to totally eliminate the need for writing server code or maintaining servers.
The Parse platform provides a complete backend solution for your mobile application. Our goal is to totally eliminate the need for writing server code or maintaining servers.
If you're familiar with web frameworks like Ruby on Rails, we've taken many of the same principles and applied them to our platform. In particular, our SDK is ready to use out of the box with minimal configuration on your part.
Apps
On Parse, you create an App for each of your mobile applications. Each App has its own application id and client key that you apply to your SDK install. Your account on Parse can accommodate multiple Apps. This is useful even if you have one application, since you can deploy different versions for test and production.
Objects
The ParseObject
The ParseObject
Storing data on Parse is built around the ParseObject. Each ParseObject contains key-value pairs of JSON-compatible data. This data is schemaless, which means that you don't need to specify ahead of time what keys exist on each ParseObject. You simply set whatever key-value pairs you want, and our backend will store it.
For example, let's say you're tracking high scores for a game. A single ParseObject could contain:
score: 1337, playerName: "Sean Plott", cheatMode: false
Keys must be alphanumeric strings. Values can be strings, numbers, booleans, or even arrays and objects - anything that can be JSON-encoded.
Keys must be alphanumeric strings. Values can be strings, numbers, booleans, or even arrays and objects - anything that can be JSON-encoded.
Each ParseObject has a class name that you can use to distinguish different sorts of data. For example, we could call the high score object a GameScore. We recommend that you NameYourClassesLikeThis and nameYourKeysLikeThis, just to keep your code looking pretty.
Saving Objects
Let's say you want to save the GameScore described above to the Parse Cloud. The interface is similar to a Map, plus the saveInBackground method:
ParseObject gameScore = new ParseObject("GameScore");
gameScore.put("score", 1337);
gameScore.put("playerName", "Sean Plott");
gameScore.put("cheatMode", false);
gameScore.saveInBackground();
After this code runs, you will probably be wondering if anything really happened. To make sure the data was saved, you can look at the Data Browser in your app on Parse. You should see something like this:
gameScore.put("score", 1337);
gameScore.put("playerName", "Sean Plott");
gameScore.put("cheatMode", false);
gameScore.saveInBackground();
After this code runs, you will probably be wondering if anything really happened. To make sure the data was saved, you can look at the Data Browser in your app on Parse. You should see something like this:
objectId: "xWMyZ4YEGZ", score: 1337, playerName: "Sean Plott", cheatMode: false,
createdAt:"2011-06-10T18:33:42Z", updatedAt:"2011-06-10T18:33:42Z"
There are two things to note here. You didn't have to configure or set up a new Class called GameScore before running this code. Your Parse app lazily creates this Class for you when it first encounters it.
createdAt:"2011-06-10T18:33:42Z", updatedAt:"2011-06-10T18:33:42Z"
There are two things to note here. You didn't have to configure or set up a new Class called GameScore before running this code. Your Parse app lazily creates this Class for you when it first encounters it.
There are also a few fields you don't need to specify that are provided as a convenience. objectId is a unique identifier for each saved object. createdAt and updatedAt represent the time that each object was created and last modified in the cloud. Each of these fields is filled in by Parse, so they don't exist on a ParseObject until a save operation has completed.
Retrieving Objects
Saving data to the cloud is fun, but it's even more fun to get that data out again. If you have the objectId, you can retrieve the whole ParseObject using a ParseQuery:
ParseQuery<ParseObject> query = ParseQuery.getQuery("GameScore");
query.getInBackground("xWMyZ4YEGZ", new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
if (e == null) {
// object will be your game score
} else {
// something went wrong
}
}
});
To get the values out of the ParseObject, there's a getX method for each data type:
query.getInBackground("xWMyZ4YEGZ", new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
if (e == null) {
// object will be your game score
} else {
// something went wrong
}
}
});
To get the values out of the ParseObject, there's a getX method for each data type:
int score = gameScore.getInt("score");
String playerName = gameScore.getString("playerName");
boolean cheatMode = gameScore.getBoolean("cheatMode");
If you don't know what type of data you're getting out, you can call get(key), but then you probably have to cast it right away anyways. In most situations you should use the typed accessors like getString.
String playerName = gameScore.getString("playerName");
boolean cheatMode = gameScore.getBoolean("cheatMode");
If you don't know what type of data you're getting out, you can call get(key), but then you probably have to cast it right away anyways. In most situations you should use the typed accessors like getString.
The three special values have their own accessors:
String objectId = gameScore.getObjectId();
Date updatedAt = g ameScore.getUpdatedAt();
Date createdAt = gameScore.getCreatedAt();
If you need to refresh an object you already have with the latest data that is in the cloud, you can call the fetchInBackground method like so:
Date updatedAt = g ameScore.getUpdatedAt();
Date createdAt = gameScore.getCreatedAt();
If you need to refresh an object you already have with the latest data that is in the cloud, you can call the fetchInBackground method like so:
myObject.fetchInBackground(new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
if (e == null) {
// Success!
} else {
// Failure!
}
}
});
The code in the GetCallback will be run on the main thread.
public void done(ParseObject object, ParseException e) {
if (e == null) {
// Success!
} else {
// Failure!
}
}
});
The code in the GetCallback will be run on the main thread.
The Local Datastore
Parse also lets you store objects in a local datastore on the Android device itself. You can use this for data that doesn't need to be saved to the cloud, but this is especially useful for temporarily storing data so that it can be synced later. To enable the datastore, call Parse.enableLocalDatastore() in your Application constructor before calling Parse.initialize(). Once the local datastore is enabled, you can store an object by pinning it.
ParseObject gameScore = new ParseObject("GameScore");
gameScore.put("score", 1337);
gameScore.put("playerName", "Sean Plott");
gameScore.put("cheatMode", false);
gameScore.pinInBackground();
As with saving, this recursively stores every object and file that gameScore points to, if it has been fetched from the cloud. Whenever you save changes to the object, or fetch new changes from Parse, the copy in the datastore will be automatically updated, so you don't have to worry about it.
gameScore.put("score", 1337);
gameScore.put("playerName", "Sean Plott");
gameScore.put("cheatMode", false);
gameScore.pinInBackground();
As with saving, this recursively stores every object and file that gameScore points to, if it has been fetched from the cloud. Whenever you save changes to the object, or fetch new changes from Parse, the copy in the datastore will be automatically updated, so you don't have to worry about it.
Retrieving Objects from the Local Datastore
Storing an object is only useful if you can get it back out. To get the data for a specific object, you can use a ParseQuery just like you would while on the network, but using the fromLocalDatastore method to tell it where to get the data.
ParseQuery<ParseObject> query = ParseQuery.getQuery("GameScore");
query.fromLocalDatastore();
query.getInBackground("xWMyZ4YEGZ", new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
if (e == null) {
// object will be your game score
} else {
// something went wrong
}
}
});
If you already have an instance of the object, you can instead use the fetchFromLocalDatastoreInBackground method.
query.fromLocalDatastore();
query.getInBackground("xWMyZ4YEGZ", new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
if (e == null) {
// object will be your game score
} else {
// something went wrong
}
}
});
If you already have an instance of the object, you can instead use the fetchFromLocalDatastoreInBackground method.
ParseObject object = ParseObject.createWithoutData("GameScore", "xWMyZ4YEGZ");
object.fetchFromLocalDatastoreInBackground(new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
if (e == null) {
// object will be your game score
} else {
// something went wrong
}
}
});
Unpinning Objects
object.fetchFromLocalDatastoreInBackground(new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
if (e == null) {
// object will be your game score
} else {
// something went wrong
}
}
});
Unpinning Objects
When you are done with the object and no longer need to keep it on the device, you can release it with unpinInBackground.
gameScore.unpinInBackground();
Saving Objects Offline
Saving Objects Offline
Most save functions execute immediately, and inform your app when the save is complete. If you don't need to know when the save has finished, you can use saveEventually instead. The advantage is that if the user currently doesn't have a network connection, saveEventually will store the update on the device until a network connection is re-established. If your app is closed before the connection is back, Parse will try again the next time the app is opened. All calls to saveEventually (and deleteEventually) are executed in the order they are called, so it is safe to call saveEventually on an object multiple times. If you have the local datastore enabled, then any object you saveEventually will be pinned as long as that save is in progress. That makes it easy to retrieve your local changes while waiting for the network to be available.
ParseObject gameScore = new ParseObject("GameScore");
gameScore.put("score", 1337);
gameScore.put("playerName", "Sean Plott");
gameScore.put("cheatMode", false);
gameScore.saveEventually();
Updating Objects
gameScore.put("score", 1337);
gameScore.put("playerName", "Sean Plott");
gameScore.put("cheatMode", false);
gameScore.saveEventually();
Updating Objects
Updating an object is simple. Just set some new data on it and call one of the save methods. Assuming you have saved the object and have the objectId, you can retrieve the ParseObject using a ParseQuery and update its data:
ParseQuery<ParseObject> query = ParseQuery.getQuery("GameScore");
// Retrieve the object by id
query.getInBackground("xWMyZ4YEGZ", new GetCallback<ParseObject>() {
public void done(ParseObject gameScore, ParseException e) {
if (e == null) {
// Now let's update it with some new data. In this case, only cheatMode and score
// will get sent to the Parse Cloud. playerName hasn't changed.
gameScore.put("score", 1338);
gameScore.put("cheatMode", true);
gameScore.saveInBackground();
}
}
});
Parse automatically figures out which data has changed so only "dirty" fields will be transmitted during a save. You don't need to worry about squashing data in the cloud that you didn't intend to update.
query.getInBackground("xWMyZ4YEGZ", new GetCallback<ParseObject>() {
public void done(ParseObject gameScore, ParseException e) {
if (e == null) {
// Now let's update it with some new data. In this case, only cheatMode and score
// will get sent to the Parse Cloud. playerName hasn't changed.
gameScore.put("score", 1338);
gameScore.put("cheatMode", true);
gameScore.saveInBackground();
}
}
});
Parse automatically figures out which data has changed so only "dirty" fields will be transmitted during a save. You don't need to worry about squashing data in the cloud that you didn't intend to update.
Counters
The above example contains a common use case. The "score" field is a counter that we'll need to continually update with the player's latest score. Using the above method works but it's cumbersome and can lead to problems if you have multiple clients trying to update the same counter.
To help with storing counter-type data, Parse provides methods that atomically increment (or decrement) any number field. So, the same update can be rewritten as:
gameScore.increment("score");
gameScore.saveInBackground();
You can also increment by any amount using increment(key, amount).
gameScore.saveInBackground();
You can also increment by any amount using increment(key, amount).
Arrays
To help with storing array data, there are three operations that can be used to atomically change an array field:
add and addAll append the given objects to the end of an array field.
addUnique and addAllUnique add only the given objects which aren't already contained in an array field to that field. The position of the insert is not guaranteed.
removeAll removes all instances of the given objects from an array field.
For example, we can add items to the set-like "skills" field like so:
addUnique and addAllUnique add only the given objects which aren't already contained in an array field to that field. The position of the insert is not guaranteed.
removeAll removes all instances of the given objects from an array field.
For example, we can add items to the set-like "skills" field like so:
gameScore.addAllUnique("skills", Arrays.asList("flying", "kungfu"));
gameScore.saveInBackground();
Note that it is not currently possible to atomically add and remove items from an array in the same save. You will have to call save in between every different kind of array operation.
gameScore.saveInBackground();
Note that it is not currently possible to atomically add and remove items from an array in the same save. You will have to call save in between every different kind of array operation.
Deleting Objects
To delete an object from the Parse Cloud:
myObject.delete InBackground();
If you want to run a callback when the delete is confirmed, you can provide a DeleteCallback to the deleteInBackground method. If you want to block the calling thread, you can use the delete method.
If you want to run a callback when the delete is confirmed, you can provide a DeleteCallback to the deleteInBackground method. If you want to block the calling thread, you can use the delete method.
You can delete a single field from an object with the remove method:
// After this, the playerName field will be empty
myObject.remove("playerName");
myObject.remove("playerName");
// Saves the field deletion to the Parse Cloud
myObject.saveInBackground();
Relational Data
myObject.saveInBackground();
Relational Data
Objects can have relationships with other objects. To model this behavior, any ParseObject can be used as a value in other ParseObjects. Internally, the Parse framework will store the referred-to object in just one place, to maintain consistency.
For example, each Comment in a blogging app might correspond to one Post. To create a new Post with a single Comment, you could write:
// Create the post
ParseObject myPost = new ParseObject("Post");
myPost.put("title", "I'm Hungry");
myPost.put("content", "Where should we go for lunch?");
ParseObject myPost = new ParseObject("Post");
myPost.put("title", "I'm Hungry");
myPost.put("content", "Where should we go for lunch?");
// Create the comment
ParseObject myComment = new ParseObject("Comment");
myComment.put("content", "Let's do Sushirrito.");
ParseObject myComment = new ParseObject("Comment");
myComment.put("content", "Let's do Sushirrito.");
// Add a relation between the Post and Comment
myComment.put("parent", myPost);
myComment.put("parent", myPost);
// This will save both myPost and myComment
myComment.saveInBackground();
You can also link objects using just their objectIds like so:
myComment.saveInBackground();
You can also link objects using just their objectIds like so:
// Add a relation between the Post with objectId "1zEcyElZ80" and the comment
myComment.put("parent", ParseObject.createWithoutData("Post", "1zEcyElZ80"));
By default, when fetching an object, related ParseObjects are not fetched. These objects' values cannot be retrieved until they have been fetched like so:
myComment.put("parent", ParseObject.createWithoutData("Post", "1zEcyElZ80"));
By default, when fetching an object, related ParseObjects are not fetched. These objects' values cannot be retrieved until they have been fetched like so:
fetchedComment.getParseObject("post")
.fetchIfNeededInBackground(new GetCallback<ParseObject>() {
public void done(ParseObject post, ParseException e) {
String title = post.getString("title");
// Do something with your new title variable
}
});
.fetchIfNeededInBackground(new GetCallback<ParseObject>() {
public void done(ParseObject post, ParseException e) {
String title = post.getString("title");
// Do something with your new title variable
}
});
You can also model a many-to-many relation using the ParseRelation object. This works similar to List, except that you don't need to download all the ParseObjects in a relation at once. This allows ParseRelation to scale to many more objects than the List approach. For example, a User may have many Posts that they might like. In this case, you can store the set of Posts that a User likes using getRelation. In order to add a post to the list, the code would look something like:
ParseUser user = ParseUser.getCurrentUser();
ParseRelation<ParseObject> relation = user.getRelation("likes");
relation.add(post);
user.saveInBackground();
You can remove a post from the ParseRelation with something like:
ParseRelation<ParseObject> relation = user.getRelation("likes");
relation.add(post);
user.saveInBackground();
You can remove a post from the ParseRelation with something like:
relation.remove(post);
By default, the list of objects in this relation are not downloaded. You can get the list of Posts by calling findInBackground on the ParseQuery returned by getQuery. The code would look like:
By default, the list of objects in this relation are not downloaded. You can get the list of Posts by calling findInBackground on the ParseQuery returned by getQuery. The code would look like:
relation.getQuery().findInBackground(new FindCallback<ParseObject>() {
void done(List<ParseObject> results, ParseException e) {
if (e != null) {
// There was an error
} else {
// results have all the Posts the current user liked.
}
}
});
If you want only a subset of the Posts you can add extra constraints to the ParseQuery returned by getQuery. The code would look something like:
void done(List<ParseObject> results, ParseException e) {
if (e != null) {
// There was an error
} else {
// results have all the Posts the current user liked.
}
}
});
If you want only a subset of the Posts you can add extra constraints to the ParseQuery returned by getQuery. The code would look something like:
ParseQuery<ParseObject> query = relation.getQuery();
// Add other query constraints.
For more details on ParseQuery, please look at the query portion of this guide. A ParseRelation behaves similar to a List for querying purposes, so any queries you can do on lists of objects (other than include) you can do on ParseRelation.
// Add other query constraints.
For more details on ParseQuery, please look at the query portion of this guide. A ParseRelation behaves similar to a List for querying purposes, so any queries you can do on lists of objects (other than include) you can do on ParseRelation.
Data Types
So far we've used values with type String, int, bool, and ParseObject. Parse also supports java.util.Date, byte[], and JSONObject.NULL.
You can nest JSONObject and JSONArray objects to store more structured data within a single ParseObject.
Some examples:
int myNumber = 42;
String myString = "the number is " + myNumber;
Date myDate = new Date();
String myString = "the number is " + myNumber;
Date myDate = new Date();
JSONArray myArray = new JSONArray();
myArray.put(myString);
myArray.put(myNumber);
myArray.put(myString);
myArray.put(myNumber);
JSONObject myObject = new JSONObject();
myObject.put("number", myNumber);
myObject.put("string", myString);
myObject.put("number", myNumber);
myObject.put("string", myString);
byte[] myData = { 4, 8, 16, 32 };
ParseObject bigObject = new ParseObject("BigObject");
bigObject.put("myNumber", myNumber);
bigObject.put("myString", myString);
bigObject.put("myDate", myDate);
bigObject.put("myData", myData);
bigObject.put("myArray", myArray);
bigObject.put("myObject", myObject);
bigObject.put("myNull", JSONObject.NULL);
bigObject.saveInBackground();
We do not recommend storing large pieces of binary data like images or documents using byte[] fields on ParseObject. ParseObjectss should not exceed 128 kilobytes in size. To store more, we recommend you use ParseFile. See the guide section for more details.
bigObject.put("myNumber", myNumber);
bigObject.put("myString", myString);
bigObject.put("myDate", myDate);
bigObject.put("myData", myData);
bigObject.put("myArray", myArray);
bigObject.put("myObject", myObject);
bigObject.put("myNull", JSONObject.NULL);
bigObject.saveInBackground();
We do not recommend storing large pieces of binary data like images or documents using byte[] fields on ParseObject. ParseObjectss should not exceed 128 kilobytes in size. To store more, we recommend you use ParseFile. See the guide section for more details.
For more information about how Parse handles data, check out our documentation on Data & Security.
Queries
Basic Queries
Basic Queries
In many cases, getInBackground isn't powerful enough to specify which objects you want to retrieve. The ParseQuery offers different ways to retrieve a list of objects rather than just a single object.
The general pattern is to create a ParseQuery, put conditions on it, and then retrieve a List of matching ParseObjects using the findInBackground method with a FindCallback. For example, to retrieve scores with a particular playerName, use the whereEqualTo method to constrain the value for a key:
ParseQuery<ParseObject> query = ParseQuery.getQuery("GameScore");
query.whereEqualTo("playerName", "Dan Stemkoski");
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 works similarly to getInBackground in that it assures the network request is done on a background thread, and runs its callback in the main thread.
query.whereEqualTo("playerName", "Dan Stemkoski");
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 works similarly to getInBackground in that it assures the network request is done on a background thread, and runs its callback in the main thread.
Query Constraints
There are several ways to put constraints on the objects found by a ParseQuery. You can filter out objects with a particular key-value pair with whereNotEqualTo:
query.whereNotEqualTo("playerName", "Michael Yabuti");
You can give multiple constraints, and objects will only be in the results if they match all of the constraints. In other words, it's like an AND of constraints.
You can give multiple constraints, and objects will only be in the results if they match all of the constraints. In other words, it's like an AND of constraints.
query.whereNotEqualTo("playerName", "Michael Yabuti");
query.whereGreaterThan("playerAge", 18);
You can limit the number of results with setLimit. By default, results are limited to 100, but anything from 1 to 1000 is a valid limit:
query.whereGreaterThan("playerAge", 18);
You can limit the number of results with setLimit. By default, results are limited to 100, but anything from 1 to 1000 is a valid limit:
query.setLimit(10); // limit to at most 10 results
If you want exactly one result, a more convenient alternative may be to use getFirst or getFirstBackground instead of using find.
If you want exactly one result, a more convenient alternative may be to use getFirst or getFirstBackground instead of using find.
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.");
}
}
});
You can skip the first results with setSkip. This can be useful for pagination:
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.");
}
}
});
You can skip the first results with setSkip. This can be useful for pagination:
query.setSkip(10); // skip the first 10 results
For sortable types like numbers and strings, you can control the order in which results are returned:
For sortable types like numbers and strings, you can control the order in which results are returned:
// Sorts the results in ascending order by the score field
query.orderByAscending("score");
query.orderByAscending("score");
// Sorts the results in descending order by the score field
query.orderByDescending("score");
You can add more sort keys to the query as follows:
query.orderByDescending("score");
You can add more sort keys to the query as follows:
// Sorts the results in ascending order by the score field if the previous sort keys are equal.
query.addAscendingOrder("score");
query.addAscendingOrder("score");
// Sorts the results in descending order by the score field if the previous sort keys are equal.
query.addDescendingOrder("score");
For sortable types, you can also use comparisons in queries:
query.addDescendingOrder("score");
For sortable types, you can also use comparisons in queries:
// Restricts to wins < 50
query.whereLessThan("wins", 50);
query.whereLessThan("wins", 50);
// Restricts to wins <= 50
query.whereLessThanOrEqualTo("wins", 50);
query.whereLessThanOrEqualTo("wins", 50);
// Restricts to wins > 50
query.whereGreaterThan("wins", 50);
query.whereGreaterThan("wins", 50);
// Restricts to wins >= 50
query.whereGreaterThanOrEqualTo("wins", 50);
If you want to retrieve objects matching several different values, you can use whereContainedIn, providing a collection of acceptable values. This is often useful to replace multiple queries with a single query. For example, if you want to retrieve scores made by any player in a particular list:
query.whereGreaterThanOrEqualTo("wins", 50);
If you want to retrieve objects matching several different values, you can use whereContainedIn, providing a collection of acceptable values. This is often useful to replace multiple queries with a single query. For example, if you want to retrieve scores made by any player in a particular list:
String[] names = {"Jonathan Walsh", "Dario Wunsch", "Shawn Simon"};
query.whereContainedIn("playerName", Arrays.asList(names));
If you want to retrieve objects that do not match any of several values you can use whereKey:notContainedIn:, providing an array of acceptable values. For example, if you want to retrieve scores from players besides those in a list:
query.whereContainedIn("playerName", Arrays.asList(names));
If you want to retrieve objects that do not match any of several values you can use whereKey:notContainedIn:, providing an array of acceptable values. For example, if you want to retrieve scores from players besides those in a list:
String[] names = {"Jonathan Walsh", "Dario Wunsch", "Shawn Simon"};
query.whereNotContainedIn("playerName", Arrays.asList(names));
If you want to retrieve objects that have a particular key set, you can use whereExists. Conversely, if you want to retrieve objects without a particular key set, you can use whereDoesNotExist.
query.whereNotContainedIn("playerName", Arrays.asList(names));
If you want to retrieve objects that have a particular key set, you can use whereExists. Conversely, if you want to retrieve objects without a particular key set, you can use whereDoesNotExist.
// Finds objects that have the score set
query.whereExists("score");
query.whereExists("score");
// Finds objects that don't have the score set
query.whereDoesNotExist("score");
You can use the whereMatchesKeyInQuery method to get objects where a key matches the value of a key in a set of objects resulting from another query. For example, if you have a class containing sports teams and you store a user's hometown in the user class, you can issue one query to find the list of users whose hometown teams have winning records. The query would look like:
query.whereDoesNotExist("score");
You can use the whereMatchesKeyInQuery method to get objects where a key matches the value of a key in a set of objects resulting from another query. For example, if you have a class containing sports teams and you store a user's hometown in the user class, you can issue one query to find the list of users whose hometown teams have winning records. The query would look like:
ParseQuery<ParseObject> teamQuery = ParseQuery.getQuery("Team");
teamQuery.whereGreaterThan("winPct", 0.5);
ParseQuery<ParseUser> userQuery = ParseUser.getQuery();
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
}
});
Conversely, to get objects where a key does not match the value of a key in a set of objects resulting from another query, use whereDoesNotMatchKeyInQuery. For example, to find users whose hometown teams have losing records:
teamQuery.whereGreaterThan("winPct", 0.5);
ParseQuery<ParseUser> userQuery = ParseUser.getQuery();
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
}
});
Conversely, to get objects where a key does not match the value of a key in a set of objects resulting from another query, use whereDoesNotMatchKeyInQuery. For example, to find users whose hometown teams have losing records:
ParseQuery<ParseUser> losingUserQuery = ParseUser.getQuery();
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
}
});
You can restrict the fields returned by calling selectKeys with a collection of keys. To retrieve documents that contain only the score and playerName fields (and also special built-in fields such as objectId, createdAt, and updatedAt):
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
}
});
You can restrict the fields returned by calling selectKeys with a collection of keys. To retrieve documents that contain only the score and playerName fields (and also special built-in fields such as objectId, createdAt, and updatedAt):
ParseQuery<ParseObject> query = ParseQuery.getQuery("GameScore");
query.selectKeys(Arrays.asList("playerName", "score"));;
List<ParseObject> results = query.find();
The remaining fields can be fetched later by calling one of the fetchIfNeeded variants on the returned objects:
query.selectKeys(Arrays.asList("playerName", "score"));;
List<ParseObject> results = query.find();
The remaining fields can be fetched later by calling one of the fetchIfNeeded variants on the returned objects:
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.
}
});
Queries on Array Values
object.fetchIfNeededInBackground(new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
// all fields of the object will now be available here.
}
});
Queries on Array Values
If a key contains an array value, you can search for objects where the key's array value contains 2 by:
// Find objects where the array in arrayKey contains the number 2.
query.whereEqualTo("arrayKey", 2);
You can also search for objects where the key's array value contains each of the values 2, 3, and 4 with the following:
query.whereEqualTo("arrayKey", 2);
You can also search for objects where the key's array value contains each of the values 2, 3, and 4 with the following:
// 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);
Queries on String Values
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(2);
numbers.add(3);
numbers.add(4);
query.whereContainsAll("arrayKey", numbers);
Queries on String Values
Use whereStartsWith to restrict to string values that start with a particular string. Similar to a MySQL LIKE operator, this is indexed so it is efficient for large datasets:
// Finds barbecue sauces that start with "Big Daddy's".
ParseQuery<ParseObject> query = ParseQuery.getQuery("BarbecueSauce");
query.whereStartsWith("name", "Big Daddy's");
ParseQuery<ParseObject> query = ParseQuery.getQuery("BarbecueSauce");
query.whereStartsWith("name", "Big Daddy's");
If you're trying to implement a generic search feature, we recommend taking a look at this blog post: Implementing Scalable Search on a NoSQL Backend.
Relational Queries
Relational Queries
There are several ways to issue queries for relational data. If you want to retrieve objects where a field matches a particular ParseObject, you can use whereEqualTo just like for other data types. For example, if each Comment has a Post object in its post field, you can fetch comments for a particular Post:
// 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
}
});
If you want to retrieve objects where a field contains a ParseObject that matches a different query, you can use whereMatchesQuery. Note that the default limit of 100 and maximum limit of 1000 apply to the inner query as well, so with large data sets you may need to construct queries carefully to get the desired behavior. In order to find comments for posts containing images, you can do:
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
}
});
If you want to retrieve objects where a field contains a ParseObject that matches a different query, you can use whereMatchesQuery. Note that the default limit of 100 and maximum limit of 1000 apply to the inner query as well, so with large data sets you may need to construct queries carefully to get the desired behavior. In order to find comments for posts containing images, you can do:
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.
}
});
If you want to retrieve objects where a field contains a ParseObject that does not match a different query, you can use whereDoesNotMatchQuery. In order to find comments for posts without images, you can do:
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.
}
});
If you want to retrieve objects where a field contains a ParseObject that does not match a different query, you can use whereDoesNotMatchQuery. In order to find comments for posts without images, you can do:
ParseQuery<ParseObject> innerQuery = ParseQuery.getQuery("Post");
innerQuery.whereExists("image");
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.
}
});
In some situations, you want to return multiple types of related objects in one query. You can do this with the include method. For example, let's say you are retrieving the last ten comments, and you want to retrieve their related posts at the same time:
innerQuery.whereExists("image");
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.
}
});
In some situations, you want to return multiple types of related objects in one query. You can do this with the include method. For example, let's say you are retrieving the last ten comments, and you want to retrieve their related posts at the same time:
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");
}
}
});
You can also do multi level includes using dot notation. If you wanted to include the post for a comment and the post's author as well you can do:
// 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");
}
}
});
You can also do multi level includes using dot notation. If you wanted to include the post for a comment and the post's author as well you can do:
query.include("post.author");
You can issue a query with multiple fields included by calling include multiple times. This functionality also works with ParseQuery helpers like getFirst() and getInBackground().
You can issue a query with multiple fields included by calling include multiple times. This functionality also works with ParseQuery helpers like getFirst() and getInBackground().
No comments:
Post a Comment