【问题标题】:Firestore Collection Group Queries for showing Items based on Category Names基于类别名称显示项目的 Firestore 集合组查询
【发布时间】:2021-07-10 16:45:50
【问题描述】:

我正在使用管理应用程序和餐厅应用程序创建多个餐厅在线订购 Android 应用程序。在用户应用程序中,有一个类别部分,用户可以在其中查看基于类别名称的项目列表。

我正在使用 Firestore 来保存和检索数据。在管理应用程序中,我可以添加餐厅及其菜单项。我已将数据库设置为如下结构。

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

请参阅下面的屏幕截图以更好地理解

1st Image Screenshot 2nd Image Screenshot

由于我们可以在文档下添加子集合,我这样做是为了添加菜单项,并没有考虑以后根据类别项名称获取类别。

下面是我的APP截图。

App Screenshot

现在,当我尝试获取项目时,问题就出现了。我对此进行了很多搜索,最终找到了 Firestore Group Queries。我也在应用程序中实现了相同的功能,但没有得到结果。所有的课程都在下面。

FoodsFromCategories.java(活动类)

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(模型类)

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(适配器类)

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

更新:请检查此代码。我已经遍历了所有文档 ID(即餐厅 ID)并将它们添加到列表中。现在我正在使用字符串的 for 循环从 MenuItems 获取数据。请检查一下。 这是在 Activity 类中

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



            }

        }
    });

【问题讨论】:

  • 您好,Subham,欢迎来到 StackOverflow! :) 你能澄清一下“但没有得到结果”这句话吗?
  • 我想通过点击类别项名称来获取下一个活动中的特定菜单项。
  • 在使用collectionGroup() 时,这段代码中究竟有什么不符合您的预期?请回复@AlexMamo
  • @AlexMamo 查询查询 = collectionReference.orderBy("MenuItems").whereEqualTo("itemCat", catnameref);
  • collectionReference 是如何定义的?

标签: java android firebase google-cloud-firestore


【解决方案1】:

您的代码中的问题在于您试图根据不存在的属性对文档进行排序。 “MenuItems”实际上是一个子集合而不是一个属性,因此您可以执行订单:

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

要获取与单个用户对应的所有订单,请使用以下查询:

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

这就是您应该传递给“setQuery()”方法的查询。如果你需要特定的订单,那么你也可以添加一个.orderBy("someProperty")调用,在这种情况下an index is required

但是,如果要获取所有用户的所有订单,则需要一个集合组查询:

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

这意味着此查询将获取每个用户的每个“MenuItems”集合中存在的所有文档。

【讨论】:

  • 好的,我理解你的说法,但我不想从特定的文档 ID 中获取项目,例如 CollectionReference menuItemsRef = rootRef.collection("Restaurants").document("testuser1").collection (“菜单项”);
  • 我需要遍历所有文档 ID,然后从那里我需要从子集合“MenuItems”中收集具有相同类别名称的菜单项
  • 如果您不想只获取单个用户的订单,那么您拥有的唯一选项是集合组查询。也许这个answer 也有帮助。
  • 嘿,@Alex Mamo 请检查这个问题的更新。
  • 当你遇到新问题时,最好用你所做的一切创建一个新问题,而不是更新它。我就是这样,我和其他开发者,可以看看并尝试提供帮助。
【解决方案2】:

我只在 Flutter 中做过这个,但看起来你需要实际使用一个集合组。 您的查询应该是这样的:

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

请记住,您还需要创建相应的索引。请参阅此处的文档: https://firebase.google.com/docs/firestore/query-data/queries#collection-group-query

【讨论】:

  • 在此查询中,您可以直接从 Firestore 对象调用集合组。并且“Menuitems”在 Restaurants 集合下,所以我不是必须使用 Restaurants 集合吗?
  • 请回复以上问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-02
  • 2016-10-25
  • 1970-01-01
  • 2017-05-01
相关资源
最近更新 更多