Relational Query Parse.com android - android

So I'm Implementing an app using Parse.com as back end, There is basically 3 class in Parse. The first one User where I have the User's Information, and Gallery where I have images "like Instagram, and Finally Follow Class where I have the relation following and followers.
Now I have an activity where I have to display all the images for the people I'm following only. I couldn't write a correct relational queries to get the correct result.
so this is the code that display all the images in the database not only for the people I'm following.
public class FollowingImages extends ParseQueryAdapter<ParseObject> {
public FollowingImages (Context context) {
super(context, new ParseQueryAdapter.QueryFactory<ParseObject>() {
public ParseQuery create() {
ParseQuery<ParseObject> query = ParseQuery.getQuery("Gallery");
query.include("createdBy");
return query;
}
});
}
// Customize the layout by overriding getItemView
#Override
public View getItemView(final ParseObject object, View v, ViewGroup parent) {
if (v == null) {
v = View.inflate(getContext(), R.layout.list_item, null);
}
super.getItemView(object, v, parent);
// retrieving the Images from Parse.com
return v;
}
I don't know where should I apply the relational query in the constructor or inside getItemView.
please any help would be highly appreciated.

You will want to apply constraints to your query.
ParseQuery<ParseObject> query = ParseQuery.getQuery("Gallery");
query.whereEqualTo("createdBy", "theUserId");
query.findInBackground(new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
if (object == null) {
Log.d("score", "The find request failed.");
} else {
Log.d("score", "Retrieved the object.");
}
}
});
See the official guide for more details.

You could use the matchesKeyInQuery constraint method.
You can use the matchesKeyInQuery method to get objects where a key matches the value of a key in a set of objects resulting from another query.
(after parse docs)
So in your case (I am writing it by hand) it may be something like:
ParseQuery<Follow> whoDoIFollow = ParseQuery.getQuery("Follow")
.select("From")
.whereEqualTo("To", <user>);
ParseQuery<Gallery> theirImages = ParseQuery.getQuery("Gallery")
.whereMatchesKeyInQuery("createdBy", "From", whoDoIFollow);
If I am correct that should be an optimal way from the point of data transferred as everything happens on the server side and you only get the results(images).
Just replace
public FollowingImages (Context context) {
super(context, new ParseQueryAdapter.QueryFactory<ParseObject>() {
public ParseQuery create() {
ParseQuery<ParseObject> whoDoIFollow = ParseQuery.getQuery("Follow")
.select("From")
.whereEqualTo("To", <user>);
ParseQuery<ParseObject> theirImages = ParseQuery.getQuery("Gallery")
.whereMatchesKeyInQuery("createdBy", "From", whoDoIFollow);
return theirImages;
}
});
}

Related

How to query in CouchDB by docType?

I'm trying to use the below query to get my documents by passing the value of docType [template or audit]; however, it is not showing the correct results.
Data.getData(database, "audit").run();
public static Query getData(Database database, final String type) {
View view = database.getView("data");
if (view.getMap() == null) {
view.setMap(new Mapper() {
#Override
public void map(Map<String, Object> document, Emitter emitter) {
if(document.get("docType").equals(type)){
emitter.emit(document.get("_id"), null);
}
}
}, "4");
}
return view.createQuery();
}
As far as I know, you might want to creat an index like this:
function (doc) {
if (doc.type) {
emit(doc.type, doc._id);
}
}
The above function creates an index for you sorted according to doc.type. Then you can do your queries faster.

Android Parse query returning Empty List

I have a parse class named "classA". I want to build a query where I want to search for rows in "classA" having certain "objectId". I have written the following code. But it always returns an empty list of ParseObjects. I have tried with separate columns existing in "classA". All the time, empty list returned. Please help.
I have used this query before on another class "classB" inside the same application and that works perfectly. I have also tried, "try-catch" block implementation using "query.find". That also returns empty list. Thanks in advance. Please explain what's wrong.
Need more code snippets, please let me know.
Button btn = (Button) findViewById(R.id.query_btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EditText objIdET= (EditText) findViewById(R.id.obj_id);
String objId= objIdET.getText().toString();
Log.d("check", objId); // Prints correct value here..
ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("classA");
fridgeID.whereEqualTo("objectId", objId);
List<ParseObject> lp = new ArrayList<ParseObject>();
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
Log.d("#results", String.valueOf(objects.size()));
}
});
}
}
});
Replace FridgeId with query
ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("classA");
query.whereEqualTo("objectId", objId);
List<ParseObject> lp = new ArrayList<ParseObject>();
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
Log.d("#results", String.valueOf(objects.size()));
}
});
Use getInBackground() if you have objectId of that row.
ParseQuery<ParseObject> query = ParseQuery.getQuery("classA");
query.getInBackground(objId, new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
if (e == null) {
Log.d("#results", String.valueOf(objects.size()));
} else {
// Handle the error
}
}
}
Call findInBackground() if you don't have objectId and setting some condition. You can also set condition on objectId field like this.
ParseQuery<ParseObject> query = ParseQuery.getQuery("classA");
query.whereEqualTo("objectId", objId);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
Log.d("#results", String.valueOf(objects.size()));
} else {
// Handle the error
}
}
}
You are getting an empty list of Parse objects because there aren't any rows corresponding to the user (which you are logged in with).
Parse.com implements privacy of its data by using a field called ACL. So if user A adds an entry to your table, by default the ACL is set to Read+Write for User A and none for other users. So user B will not be able to find any objects of userA.
To read more : https://parse.com/docs/android/guide#security
If you want to create a mechanism by which only users belonging to a certain group can read+write each other's objects, you can Roles (Parse feature).
https://parse.com/docs/android/guide#roles
Check if you have set the correct keys when you initialize the parse in your application.
If you want to get list of users, and ParseQuery.getQuery doesn't work - try this:
val query: ParseQuery<ParseUser> = ParseUser.getQuery()
query.findInBackground() {...}

ParseQueryAdapter; using class in Android

I feel like a broken record.
After many attempts, I have failed at getting a listview through Parse data to display a specific set of information.
Here is my model...this is all data from users:
#ParseClassName("Midwifefirm")
public class Midwifefirm extends ParseObject {
public Midwifefirm() {
// A default constructor is required.
}
//practice name
public String getPracticeName() {
return getString("practicename");
}
public void setPracticeName(String practicename) {
put("practicename", practicename);
}
//education
public String getEducation() {
return getString("education");
}
public void setEducation(String education) {
put("education", education);
}
//years in practice
public String getYearsinPractice() {
return getString("yearsinpractice");
}
public void setYearsinPractice(String yearsinpractice) {
put("yearsinpractice", yearsinpractice);
}
//practice philosophy
public String getPracticePhilosophy() {
return getString("practicephilosophy");
}
public void setPracticePhilosophy(String practicephilosophy) {
put("practicephilosophy", practicephilosophy);
}
I have this adapter; I am wondering what to place in the query section, as I just want to pull the data into the ListView that is defined in the data model:
public class CustomMidwifeAdapter extends ParseQueryAdapter<Midwifefirm> {
public CustomMidwifeAdapter(Context context) {
super(context, new ParseQueryAdapter.QueryFactory<Midwifefirm>() {
public ParseQuery<Midwifefirm> create() {
// Here we can configure a ParseQuery to display
// only top-rated meals.
ParseQuery query = new ParseQuery("Midwives");
return query;
}
});
}
#Override
public View getItemView(Midwifefirm midwifefirm, View view, ViewGroup parent) {
if (view == null) {
view = View.inflate(getContext(), R.layout.activity_midwife_result_list, null);
}
//use midwifefirm as item view/list
super.getItemView(midwifefirm, view, parent);
// find in layout the practice name
TextView titleTextView = (TextView) view.findViewById(R.id.practicename);
//in the midwifefirm data model, call getPracticename
titleTextView.setText(midwifefirm.getString("practicename"));
// Add education view
TextView EducationView = (TextView) view.findViewById(R.id.education);
EducationView.setText(midwifefirm.getString("education"));
// Add yearsexperience view
TextView ExperienceView = (TextView) view.findViewById(R.id.yearsinpractice);
ExperienceView.setText(midwifefirm.getString("yearsinpractice"));
//Add practice philosophy view
TextView PracticePhilosophyView = (TextView) view.findViewById(R.id.practicephilosophy);
PracticePhilosophyView.setText(midwifefirm.getString("practicephilosophy"));
return view;
}
}
And here is the Main Activity:
public class MidwifeResultList extends ListActivity {
private ParseQueryAdapter<ParseObject> mainAdapter;
private CustomMidwifeAdapter midwifeListAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//initialize main ParseQueryAdapter
mainAdapter = new ParseQueryAdapter<ParseObject>(this, Midwifefirm.class);
//which keys in Midwife object
mainAdapter.setTextKey("practicename");
mainAdapter.setTextKey("education");
mainAdapter.setTextKey("yearsinpractice");
mainAdapter.setTextKey("practicephilosophy");
// Initialize the subclass of ParseQueryAdapter
midwifeListAdapter = new CustomMidwifeAdapter(this);
// Default view is all meals
setListAdapter(mainAdapter);
}
Every time I run this, I get no results.
Thanks in advance for any help
Michael
I can tell you why I think it fails now and I can tell you why I'm very sure it will fail after you sort out the current issue.
It seems that you're trying to use different classes
#ParseClassName("Midwifefirm")
public class Midwifefirm extends ParseObject {
and
ParseQuery query = new ParseQuery("Midwives");
You need to be consistent and use the same name. Either use Midwives or Midwifefirm for both. Let's assume you picked the latter. You're also saying
all that is stored in the user table...wasn't sure if I needed to create new tables.
The query above wants to get all entries of type Midwives. If there's no such type, it'll return nothing. So you have two options:
In you Parse dashboard, reate a class Midwifefirm (don't forget to update the String inside #ParseClassName above) and store your Midwifefirm data in there. You don't need to change your query for this.
Add a column to your ParseUser class, such as type, that you can set to Midwifefirm or whatever if that user is a Midwifefirm or whatever. Then in your query you need to add:
ParseQuery query = new ParseQuery("Midwives");
query.whereEquals("type", "Midwifefirm");
I greatly prefer the former.
Anyway, once your done that, the issue is that you're not using a custom view for this. You're relying on the one provided by Android by default for ListActivity. I am fairly sure it doesn't have any of the fields you're after, so you should create a custom view for this, then at the top of onCreate in your Activity make sure you use it
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_custom_view);
By the way, the following are redundant if you populate then in getItemView anyway:
mainAdapter.setTextKey("practicename");
mainAdapter.setTextKey("education");
mainAdapter.setTextKey("yearsinpractice");
mainAdapter.setTextKey("practicephilosophy");
One final advice: if you're still having issues, set breakpoints and do some investigations first. What you need to check is:
Whether you get anything at all from Parse when you do your query. Your adapter has an useful addOnQueryLoadListener that you may use to check whether anything's been retrieved at all.
If stuff is retrieved successfully, you need to check whether the list view is populated correctly. Again, use breakpoints, this time in getItemView maybe.
I'm going to do a wild guess here using the lovely brainwrecking API help of Parse.com about ParseQueryAdapters
Before continuing, may I mind you that my experience with ParseQueryAdapters is a minimum but I think I have a basic knowledge about them + I have some experience with Parse on its own. ANYHOW,
As an example they use both these
final ParseQueryAdapter adapter = new ParseQueryAdapter(this, "Midwives");
adapter.setTextKey("name");
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
and
// Instantiate a QueryFactory to define the ParseQuery to be used for fetching items in this
// Adapter.
ParseQueryAdapter.QueryFactory<ParseObject> factory =
new ParseQueryAdapter.QueryFactory<ParseObject>() {
public ParseQuery create() {
ParseQuery query = new ParseQuery("Midwives");
return query;
}
};
// Pass the factory into the ParseQueryAdapter's constructor.
ParseQueryAdapter<ParseObject> adapter = new ParseQueryAdapter<ParseObject>(this, factory);
adapter.setTextKey("name");
// Perhaps set a callback to be fired upon successful loading of a new set of ParseObjects.
adapter.addOnQueryLoadListener(new OnQueryLoadListener<ParseObject>() {
public void onLoading() {
// Trigger any "loading" UI
}
public void onLoaded(List<ParseObject> objects, ParseException e) {
// Execute any post-loading logic, hide "loading" UI
}
});
// Attach it to your ListView, as in the example above
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
To start of, the reason why I think nothing is loading inside your list has to do with a little mixup between the initilization of your ParseQueryAdapter and your custom adapter.
You configure the basic adapter, and also initialize a custom adapter but you don't do anything with the custom adapter, tho the custom adapter seems to contain the logics to load your data model.
I think what you're looking for is something like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//initialize main ParseQueryAdapter
mainAdapter = new CustomMidwifeAdapter<ParseObject>(this);
//which keys in Midwife object
mainAdapter.setTextKey("practicename");
mainAdapter.setTextKey("education");
mainAdapter.setTextKey("yearsinpractice");
mainAdapter.setTextKey("practicephilosophy");
// Default view is all meals
setListAdapter(mainAdapter);
}
All you need to pass is the context (aka "this"), and the constructor of your custom class will handle the factory internal
super(context, new ParseQueryAdapter.QueryFactory<Midwifefirm>() {
public ParseQuery<Midwifefirm> create() {
// Here we can configure a ParseQuery to display
// only top-rated meals.
ParseQuery query = new ParseQuery("Midwives");
return query;
}
});
Tho to be honest since you do:
new ParseQueryAdapter<ParseObject>(this, Midwifefirm.class);
I wonder if you'd need to change your "QueryFactory" to
super(context, new ParseQueryAdapter.QueryFactory<Midwifefirm>() {
public ParseQuery<Midwifefirm> create() {
// Here we can configure a ParseQuery to display
// only top-rated meals.
ParseQuery query = new ParseQuery(MidWifefirm.class);
return query;
}
});
Where you pass a class to the the query rather than the tableName, but I could be wrong on that one.
Either way I hope this has helped in some way!

how can I use ParseQueryAdapter for compund queries

I'm trying to use the ParseQueryAdapter to give me a list of games. I have a separate table for storing game and player pointers. In the query I'm trying to list the games, and how many players there are.
SQL style it is like this: SELECT games,count(players) FROM games JOIN participants...
I understand how can I do that with two different ParseQueries, but it only expects a single ParseQuery.
public class GamesListAdapter extends ParseQueryAdapter<ParseObject> {
public GamesListAdapter(Context context) {
super(context, new ParseQueryAdapter.QueryFactory<ParseObject>() {
public ParseQuery create() {
ParseQuery query = new ParseQuery("Games");
return query;
}
});
}
How can I return a compound query here with counting all players from a different table?
It seems that you already found an answer yourself, but I post my solution here so other people may find it helpful.
In my case I have a User ParseObject and A UserPhoto ParseObject. I wanted to get only the Users' profile Images and set them in a ListView, but exclude the currentUser's(mine) profileImage from the results. Here is my working code.
public class CustomAdapter extends ParseQueryAdapter<ParseObject> {
public CustomAdapter(Context context) {
super(context, new ParseQueryAdapter.QueryFactory<ParseObject>() {
public ParseQuery create() {
ParseObject myUser = null;
ParseQuery<ParseObject> myUserQuery = ParseQuery.getQuery("User");
myDogQuery.whereEqualTo("user", ParseUser.getCurrentUser());
try {
myUser = myUserQuery.getFirst();
} catch (ParseException e) {
e.printStackTrace();
}
ParseQuery<ParseObject> userPhotoQuery = ParseQuery.getQuery("UserPhoto");
dogPhotoQuery.whereEqualTo("imageName", "profileImage");
dogPhotoQuery.whereNotEqualTo("user", myUser);
dogPhotoQuery.orderByDescending("createdAt");
return userPhotoQuery;
}
});
}
I would also like to see your code, if you have some time because I would like to see the "whereKeyDoesMatch function" implementation. Thank you!!

get the ParseFile from the ParseQuery

I am writing an address book APP and using the Parse service.
I also use the listview and BaseAdapter to implement the APP
There are many people I saved as the ParseObject.
And each ParseObject includes a photo saved as file.
I get all ParseObjects by :
ArrayList<ParseObject> list = new ArrayList<ParseObject>();
ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("member");
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
list = (ArrayList<ParseObject>) objects;
mMyadapter = new MyAdapter(context, list);
}
else {
}
});
in the adapter, I want to show the image from the ParseFile
My question is :
How do I get the ParseFile from the list?
I tried below code but the APP will shut down suddenly.
I wrote the getView method in the MyAdapter like below:
ParseFile pf = (ParseFile) list.get(position).get("photo1");
pf.getDataInBackground(new GetDataCallback() {
#Override
public void done(byte[] bytes, ParseException e) {
if (e == null) {
Bitmap bm = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
viewTag.imageView1.setImageBitmap(bm);
}
else {
Log.d("debug", "bad");
}
}
});
I can not use the getUrl() neither....
Can someone tell me how to modify it? Many thanks for your help!
You don't need to initialize list.
How are you setting the adapter of your ViewGroup? At the moment, you're creating a new adapter only when your ParseQuery is done. Your adapter may not be set properly.
Since list could point to new ArrayList<ParseObject>() or (ArrayList<ParseObject>) objects depending on whether ParseQuery is done, it's possible that you're calling list.get() on an invalid position.
In short, make your member variables local. Also, if MyAdapter is an anonymous class, pull that code out into a static inner class so it doesn't refer to its containing class' member variables. Use getItem() to access your ParseObjects, not list.get().

Categories

Resources