Search code examples
androidparse-platformandroid-parsequeryadapter

ParseQueryAdapter key match empty Android


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;
        }
    });

}

Solution

  • 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.