0

I am creating a Multiple Restaurant Online Ordering Android app with Admin App and Restaurant App. In the User app, a Category section is there, where users can view a list of items based on the category name.

I am using Firestore for saving and retrieving data. In the admin app, I can add a restaurant and its menu items. I have set the database like the below structure.

Restaurant
     |
     Restaurant Id (in this case I have used restaurant username for id)
       |(1st branch)                              |(2nd branch)
       MenuItems (SubCollection)     All other Properties of Restaurants
        |
        MenuId (Auto Generated Id)
          | 
          All Menu Properties

See the below screenshots for a better understanding

1st Image Screenshot 2nd Image Screenshot

As we can add Subcollections under a document, I have done so for adding the menu items and did not think of getting the categories later based on the category item name.

Below is my APP Screenshot.

App Screenshot

Now the problem arises when I am trying to fetch the items. I have searched many things regarding this and eventually found Firestore Group Queries. I have also implemented the same in the app but did not get the result. All the classes are below.

FoodsFromCategories.java (Activity Class)

public class FoodsFromCategories extends AppCompatActivity {
    RecyclerView itemrecycler;
    FirebaseFirestore firebaseFirestore;
    CollectionReference collectionReference;
    String catnameref;
    List<String> list;
    FirestoreRecyclerOptions<MenuModel> menuModelFirestoreRecyclerOptions;
    FirestoreRecyclerAdapter<MenuModel, FoodsFromCatAdapter> adapterFirestoreRecyclerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_foods_from_categories);
        catnameref = getIntent().getStringExtra("catName");
        Toolbar toolbar = findViewById(R.id.toolbarcat);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setTitle("Delicious " + catnameref);
        toolbar.setTitleTextColor(getResources().getColor(android.R.color.white));
        itemrecycler = findViewById(R.id.recyclerviewcatpage);
        itemrecycler.setLayoutManager(new LinearLayoutManager(FoodsFromCategories.this));

        firebaseFirestore = FirebaseFirestore.getInstance();
        collectionReference = firebaseFirestore.collection("Restaurants");
       list = new ArrayList<>();

       Query query = collectionReference.orderBy("MenuItems").whereEqualTo("itemCat", catnameref);

       menuModelFirestoreRecyclerOptions = new FirestoreRecyclerOptions.Builder<MenuModel>().setQuery(query, MenuModel.class).build();
       adapterFirestoreRecyclerAdapter = new FirestoreRecyclerAdapter<MenuModel, FoodsFromCatAdapter>(menuModelFirestoreRecyclerOptions) {
           @Override
           protected void onBindViewHolder(@NonNull FoodsFromCatAdapter holder, int position, @NonNull MenuModel model) {
               holder.ifromRescat.setText(model.getResname());

           }

           @NonNull
           @Override
           public FoodsFromCatAdapter onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
               View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_product_item_from_cats, parent, false);
               return  new FoodsFromCatAdapter(view);
           }
       };
       adapterFirestoreRecyclerAdapter.startListening();
       itemrecycler.setAdapter(adapterFirestoreRecyclerAdapter);

    }
}

MenuModel.java (Model Class)

public class MenuModel {
    String finalprice, itemcat, itemlargesizename, itemname, itemsmallsizename, largesizeprice, originalprice, productimage, resid, smallsizeprice, status, menuid, resname;

    public MenuModel() {
    }

    public MenuModel(String finalprice, String itemcat, String itemlargesizename, String itemname, String itemsmallsizename, String largesizeprice, String originalprice, String productimage, String resid, String smallsizeprice, String status, String menuid, String resname) {
        this.finalprice = finalprice;
        this.itemcat = itemcat;
        this.itemlargesizename = itemlargesizename;
        this.itemname = itemname;
        this.itemsmallsizename = itemsmallsizename;
        this.largesizeprice = largesizeprice;
        this.originalprice = originalprice;
        this.productimage = productimage;
        this.resid = resid;
        this.smallsizeprice = smallsizeprice;
        this.status = status;
        this.menuid = menuid;
        this.resname = resname;
    }

    public String getResname() {
        return resname;
    }

    public void setResname(String resnamecat) {
        this.resname = resnamecat;
    }

    public String getMenuid() {
        return menuid;
    }

    public void setMenuid(String menuid) {
        this.menuid = menuid;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getFinalprice() {
        return finalprice;
    }

    public void setFinalprice(String finalprice) {
        this.finalprice = finalprice;
    }

    public String getItemcat() {
        return itemcat;
    }

    public void setItemcat(String itemcat) {
        this.itemcat = itemcat;
    }

    public String getItemlargesizename() {
        return itemlargesizename;
    }

    public void setItemlargesizename(String itemlargesizename) {
        this.itemlargesizename = itemlargesizename;
    }

    public String getItemname() {
        return itemname;
    }

    public void setItemname(String itemname) {
        this.itemname = itemname;
    }

    public String getItemsmallsizename() {
        return itemsmallsizename;
    }

    public void setItemsmallsizename(String itemsmallsizename) {
        this.itemsmallsizename = itemsmallsizename;
    }

    public String getLargesizeprice() {
        return largesizeprice;
    }

    public void setLargesizeprice(String largesizeprice) {
        this.largesizeprice = largesizeprice;
    }

    public String getOriginalprice() {
        return originalprice;
    }

    public void setOriginalprice(String originalprice) {
        this.originalprice = originalprice;
    }

    public String getProductimage() {
        return productimage;
    }

    public void setProductimage(String productimage) {
        this.productimage = productimage;
    }

    public String getResid() {
        return resid;
    }

    public void setResid(String resid) {
        this.resid = resid;
    }

    public String getSmallsizeprice() {
        return smallsizeprice;
    }

    public void setSmallsizeprice(String smallsizeprice) {
        this.smallsizeprice = smallsizeprice;
    }
}

FoodsFromCatAdapter.java (Adapter Class)

public class FoodsFromCatAdapter extends RecyclerView.ViewHolder {
    public ImageView i1cat;
    public TextView inamecat, ifromRescat, ihalforfullcat, iorpricecat, iratingscat;
    public Button gotores;

    public FoodsFromCatAdapter(@NonNull View itemView) {
        super(itemView);


        i1cat = itemView.findViewById(R.id.imagecat);
        inamecat = itemView.findViewById(R.id.itemnamecat);
        ifromRescat = itemView.findViewById(R.id.fromrescat);
        ihalforfullcat = itemView.findViewById(R.id.itemhalforfullcat);
        iorpricecat = itemView.findViewById(R.id.finalpricecat);
        gotores = itemView.findViewById(R.id.gotorescat);
        iratingscat = itemView.findViewById(R.id.ratecat);
    }
}

UPDATE: Please check this code. I have looped through all the documents id's (that is the Restaurant ids) and add them to a list. Now I am using a for loop of strings to get the data from MenuItems. Please check it. This is in the Activity class

collectionReference.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            if(task.isSuccessful()){
                for(QueryDocumentSnapshot queryDocumentSnapshot:task.getResult()){
                    ResModel resModel = queryDocumentSnapshot.toObject(ResModel.class);
                    list.add(resModel.getResUserName());
                }

                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        for( String items : list){
                            Query query = collectionReference.document(items).collection("MenuItems").whereEqualTo("itemcat", catnameref);
                            menuModelFirestoreRecyclerOptions = new FirestoreRecyclerOptions.Builder<MenuModel>().setQuery(query, MenuModel.class).build();
                            adapterFirestoreRecyclerAdapter = new FirestoreRecyclerAdapter<MenuModel, FoodsFromCatAdapter>(menuModelFirestoreRecyclerOptions) {
                                @Override
                                protected void onBindViewHolder(@NonNull FoodsFromCatAdapter holder, int position, @NonNull MenuModel model) {
                                    holder.ifromRescat.setText(model.getResname());
                                    holder.inamecat.setText(model.getItemname());

                                }

                                @NonNull
                                @Override
                                public FoodsFromCatAdapter onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
                                    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_product_item_from_cats, parent, false);
                                    return  new FoodsFromCatAdapter(view);
                                }
                            };
                            adapterFirestoreRecyclerAdapter.startListening();
                            itemrecycler.setAdapter(adapterFirestoreRecyclerAdapter);
                        }
                    }
                },2000 );



            }

        }
    });

2 Answers2

0

I have only done this in Flutter, but it looks like you need to actually use a collection group. Your query should be something like this:

Query query = firebaseFirestore.collectionGroup("MenuItems").whereEqualTo("itemCat", catnameref);

Bear in mind that you will also need to create the corresponding index. See the docs here: https://firebase.google.com/docs/firestore/query-data/queries#collection-group-query

0

The problem in your code lies in the fact that you are trying to order documents according to a property that doesn't exist. "MenuItems" is actually a sub-collection and not a property so you can perform an order:

collectionReference = firebaseFirestore.collection("Restaurants");
Query query = collectionReference.orderBy("MenuItems").whereEqualTo("itemCat", catnameref);

To get all the all orders that correspond to a single user, please use the following query:

FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference menuItemsRef = rootRef.collection("Restaurants").document("testuser1").collection("MenuItems");
Query queryByItemCat = menuItemsRef.whereEqualTo("itemCat", catnameref);

That's the Query that you should pass to the "setQuery()" method. If you need a specific order, then you can also add an .orderBy("someProperty") call, a case in which an index is required.

However, if want to get all orders of all users, a collection group Query is required:

rootRef.collectionGroup("MenuItems").whereEqualTo("itemCat", catnameref);

This means that this Query will get all documents that exist in each "MenuItems" collection of each user.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • ok, I understand your statement, but i don't want to get items from specific doc id, like CollectionReference menuItemsRef = rootRef.collection("Restaurants").document("testuser1").collection("MenuItems"); – Subham Chatterjee Jul 12 '21 at 15:50
  • i need to loop through all the document ids and then from there I need to collect the menuitems which has the same category names from the Sub-Collection "MenuItems" – Subham Chatterjee Jul 12 '21 at 15:52
  • If you don't want to get only the orders of a single user, then the single option that you have is the collection group query. Maybe this [answer](https://stackoverflow.com/questions/68049541/collectiongroupquery-but-limit-search-to-subcollections-under-a-particular-docum/68049847#68049847) might also help. – Alex Mamo Jul 12 '21 at 16:00
  • Hey, @Alex Mamo please check the update on this question. – Subham Chatterjee Jul 13 '21 at 14:49
  • When you encounter new problems, it's best to create a new question with everything you have done, and not update it. I'm this way, I and **other** developers, can take a look and try to help. – Alex Mamo Jul 13 '21 at 15:38
  • Ok, I will surely do that. But could you please check the update once? – Subham Chatterjee Jul 13 '21 at 15:51