【问题标题】:Firebase Android, checking if an object (with multiple children) existsFirebase Android,检查一个对象(有多个孩子)是否存在
【发布时间】:2017-09-26 21:36:59
【问题描述】:

我正在使用 Firebase 数据库来存储用户的报告。每个用户只能提交 10 份不同的报告。

在下面的示例中,我们有一个名为“Jasna Kuljancic”的用户提交了 3 份报告。

我的问题是如何检查用户是否已经提交了特定报告?

我必须检查“location”、“mode”、“spinnerOne”的值,并将它们与用户刚刚输入的内容进行比较,如果它已经存在,则不要添加到数据库中,如果是,那么添加它。这是我的尝试:

public void checkifentryExistofNot() {
                uniqueID = mDatabaseReference.push().getKey();
                fullname = “Jasna Kuljancic”;
                CATEGORY = “Clinical First”); 

                final Report subreport = new Report(SELECTED_LOCATION,
                        locationEditText.getText().toString(),
                        modeEditText.getText().toString(),
                        Integer.parseInt(dateEditText.getText().toString()));

                mDatabaseReference.child("Students Reports").child(fullname).child(CATAGORY).addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                int numberofCount = (int) dataSnapshot.getChildrenCount();
                if (numberofCount == 0) {

                    mDatabaseReference.child("Students Reports").child(fullname).child(CATAGORY).child(uniqueID).setValue(subreport);

                }

                if (numberofCount != 0) {

                    for (DataSnapshot child : dataSnapshot.getChildren()) {
                        Report datareports = child.getValue(Report.class);
                        thelocation = datareports.getLocation();
                        themode = datareports.getMode();

                        if (thelocation.equals(locationEditText.getText().toString()) && themode.equals(modeEditText.getText().toString())) {
                            break;
                        } else {
                            mDatabaseReference.child("Students Reports").child(fullname).child(CATAGORY).child(uniqueID).setValue(subreport);
                        }
                    }
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        });
    }

我的解决方案的问题是 for 循环将检查每个报告,并且在每种情况下它都会添加或不添加新报告,但这会发生在现有报告的数量上,并且它应该只执行一次。

也就是说,如果我们有 3 个条目,并且每次都不存在,它会提交 3 次报告(这还不错)。但是,如果它检查第一个报告并且确实存在,则循环将退出,因为我在那里有一个“中断”(这很好)但是假设第二个报告将是重复的,它已经将其添加到数据库中,因为第一个条目不是重复的。

我觉得我已经完成了这项工作,应该有更快的方法来做到这一点。

【问题讨论】:

    标签: android firebase firebase-realtime-database


    【解决方案1】:

    Firebase 查询只能按单个属性排序/过滤。因此 Firebase 中没有 WHERE 子句。相反,您应该做的是耦合一个名为location_mode_spinnerOne 的复合值。您的数据库结构应如下所示:

    Firebase-root
       |
       -- Students Reports
             |
             -- Jasna Kuljancic
                   |
                   -- Clinical First
                         |
                         -- -KuVRQ4OjdfKXCNdLWzb
                                |
                                --- data: 3939393
                                |
                                --- location: "fifififi"
                                |
                                --- mode: "ododododo"
                                |
                                --- spinnerOne: "Asylum Hill Family Clinic"
                                |
                                --- location_mode_spinnerOne: "fifififi_ododododo_Asylum Hill Family Clinic"
    

    如您所见,我为每个特定类别添加了新的复合值location_mode_spinnerOne。这意味着您可以根据这个新的location_mode_spinnerOne 字段查询您的 Firebase 数据库。假设上述数据库结构正确,请使用以下代码:

    DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
    DatabaseReference categoryRef = rootRef.child("Students Reports").child(fullname).child(CATAGORY);
    ValueEventListener eventListener = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            String searchedText = "fifififi";
    
            for(DataSnapshot ds : dataSnapshot.getChildren()) {
                String location_mode_spinnerOne = ds.child("location_mode_spinnerOne").getValue(String.class);
                if(!location_mode_spinnerOne.contains(searchedText)) {
                    categoryRef.child(uniqueID).setValue(subreport);
                }
            }
        }
    
        @Override
        public void onCancelled(DatabaseError databaseError) {}
    };
    categoryRef.addListenerForSingleValueEvent(eventListener);
    

    我给了你一个搜索fifififi关键字的例子。 searchedText 文本将是用户键入的确切搜索文本。

    为了更好地理解,我建议你看看这个tutorial

    【讨论】:

    • for(DataSnapshot ds : dataSnapshot.getChildren()) { String location_mode_spinnerOne = ds.child("alltogether").getValue(String.class); if(!location_mode_spinnerOne.equals(datacombined)) { categoryref.child(uniqueID).setValue(subreport); Log.d("真棒", "提交"); } else { Log.d("真棒", "未提交"); } } 这有效,只是它向 firebase 添加数据,即使它进入“未提交”状态。这是为什么呢?
    • 非常感谢 Atif AbbAsi、mark42inbound、Alex!你的回答很有帮助!
    • 即使没有 else 循环它也会这样做,那是我最终尝试了 else 条件。
    • 但它不打印任何东西。谢谢美都!干杯!
    • 不幸的是,这对我来说很奇怪。该代码是有意义的,并且是 android 监视器,但它会不断添加数据,无论是新的还是重复的。
    【解决方案2】:

    dataSnapshot.getChildrenCount() 它会显示孩子的总数。! 您所要做的就是让模型类将您的值保存在对象中,并在编辑时检查对象是否具有相同的数据然后不更新数据,如果它不同则更新数据。!

    【讨论】:

      【解决方案3】:

      有两种方法可以解决这个问题。我认为对于第一种方法,您已经很清楚如何做到这一点。唯一缺少的是将 [a] 验证报告的唯一性和 [b] 将对象添加到数据库的顺序操作分开。可能有一个按钮来添加报告。我建议,按下按钮获取所需表的数据快照。由于报表的唯一性受限于单个用户,因此获取单个用户的所有报表。然后只需将目标报告与获取的报告进行比较并相应地继续。如果唯一,则添加或报告重复项。不同之处(w.r.t 您的代码)是不会附加事件侦听器。而且我认为您的代码处理与 Firebase 数据一致。在这里你会得到数据转储,比较然后更新它。

      另一种方法是利用 Firebase 提供的规则。基本上与第一种方法相同,但所有工作都由firebase完成。以下是仅向 Firebase 插入唯一用户名的代码:

       "usernames": {
        "$usernameid": {
        ".read": "auth != null",
          ".write": "auth != null  && (!data.exists() || !newData.exists())"
        }
       }
      

      根据您的问题,您根据三个值检查报告的唯一性。为所有三个值添加规则。这将允许为每个用户插入唯一的报告。但请务必正确添加规则,因为规则的范围必须针对单个用户,而不是针对数据库中的所有报告。

      【讨论】:

        猜你喜欢
        • 2016-09-18
        • 2021-03-11
        • 2016-09-20
        • 2017-02-25
        • 2018-08-07
        • 2023-03-12
        • 1970-01-01
        • 2017-10-24
        • 1970-01-01
        相关资源
        最近更新 更多