Firebase Andriod,检查一个对象(有多个孩子)是否存在

时间:2017-09-26 21:36:59

标签: android firebase firebase-realtime-database

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

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

Image

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

我必须检查“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次(这不是很糟糕)。但是如果它检查第一个报告并且它确实存在,那么循环将退出,因为我在那里有一个“中断”(这很好)但是让我们说第二个报告是一个重复的报告,它本来就是将它添加到数据库,因为第一个条目不是重复。希望我明白这一点。

任何帮助将不胜感激。我觉得我已经完成了这个,应该有一个更快的方法来做到这一点。

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

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

答案 2 :(得分:1)

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

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

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

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