0

I have three parse subclasses: Recipe, Ingredient, and RecipeIngredient. RecipeIngredient has a pointer to a Recipe, and a pointer to an Ingredient.

When I am trying to create a QueryFactory to get all the ingredients for a recipe. I am trying to do this with whereMatchesKeyInQuery, but the objectIds aren't matching. From the docs, it appears that this should be legal. What am I missing?

 public MeatIngredientListAdapter(Context context, final String recipeName) {
    super(context, new ParseQueryAdapter.QueryFactory<Ingredient>() {
        public ParseQuery<Ingredient> create() {

            ParseQuery<Ingredient> query = ParseQuery.getQuery(Ingredient.class);
            query.whereEqualTo("isMeatOrFat", true);

            ParseQuery<RecipeIngredient> riQuery = ParseQuery.getQuery(RecipeIngredient.class);
            riQuery.whereEqualTo("recipeName", recipeName);
            riQuery.include("ingredient");
            riQuery.whereEqualTo("isMeatOrFat", true);

            query.whereMatchesKeyInQuery("objectId", "ingredient.objectId", riQuery);

            return query;
        }
    });

}
Jennifer S
  • 1,419
  • 1
  • 24
  • 43
  • Can you explain the purpose of the sub query? Is not clear to me what the Recipe ingredient should do to the result of Ingredients returned – cYrixmorten May 19 '15 at 20:22

1 Answers1

1

In your case the use of whereMatchesKeyInQuery is overkill. I might not have enough information to make this call about your app but is seems that you would be able to cut out the need for RecipeIngredient all together if you just create a Relation of the Ingredient class inside the Recipe class. This will simplify your queries and make your app more scalable and give you features (explained below). If you had a data structure like this:

Recipe Class
 - Name (String)
 - ingredients (Relation of the Ingredient class)

Ingredient Class
 - <Columns to describe the ingredient that you already have in place>

Now you can store one recipe that "points" (using relations) to many ingredients.

So an example entry might look like this:

Recipe
 Name
  PB&J
 ingredients
  Peanut Butter //this is a relation to the Peanut Butter Ingredient object
  Jelly         //this is a relation to the Jelly Ingredient object

Ingredient
 Name
  Peanut Butter
 Calories
  ...
 Cost
  ...

And here in code we add the data to the classes:

ParseObject ingredient1 = new ParseObject(Ingredient.class);
ingredient1.put("Name", "Peanut Butter");

ParseObject ingredient2 = new ParseObject(Ingredient.class);
ingredient1.put("Name", "Jelly");


ParseObject recipe = new ParseObject("Recipe");
recipe.put("Name", "PB&J");

ParseRelation<ParseObject> relation = recipe.getRelation("ingredients");
relation.add(ingredient1);
relation.add(ingredient2);

recipe.saveInBackground();

The magic behind this setup is that we can now specify a recipe by name and get all ingredients like you wanted but we can also retrieve all recipes that have certain ingredient(s) in them (this is the beauty of a many-to-many relationship) and on top of that it simplifies your queries.

Now for the original query you wanted with this new setup:

ParseObject recipe = ...; // "PB&J" Recipe object.

ParseRelation relation = recipe.getRelation("ingredients");

// generate a query based on that relation
ParseQuery query = relation.getQuery();

query will hold all of the ingredients for the recipe object when the query is executed.

Now suppose you want to create a query where you get all of the recipes that contain a certain ingredient:

ParseObject ingredient = ...

ParseQuery<ParseObject> query = ParseQuery.getQuery("Recipe");

query.whereEqualTo("ingredients", ingredient); //use whereContainedIn for multiple ingredients

query will contain all Recipe objects that have the specified ingredient in their ingredients relation column when the query is executed.

I hope this helped you. Please let me know if I severely misunderstood the structure of your app - if so I will revise my answer if you give me new information but honestly I think the "middle man" RecipeIngredient is forcing you to complicate your app.

Max Worg
  • 2,932
  • 2
  • 20
  • 35
  • Thanks for this, @MaxWorg. I've been trying to figure out the best way to structure the data, and to get the adapters to work. I'm having a hard time figuring out how to put things in subclasses. Sometimes the documentation examples are a bit too simple for me to really understand the best way to do something. – Jennifer S May 20 '15 at 10:52
  • I have felt your pain :D The documentation in my opinion has been rather incomplete (and in some cases I have found that the documentation and examples are outdated which makes them incorrect) and I have been left on my own to figure things out many times. Let me know if I can be of any more assistance. – Max Worg May 20 '15 at 16:28
  • this is slick! But now I am trying to add steps to the recipe as another Relation, and the saving isn't working. Are you stuck with only one relation per object?? – Jennifer S May 28 '15 at 20:33