【问题标题】:Renaming keys in firebase with multiple sub-keys使用多个子键重命名firebase中的键
【发布时间】:2018-05-03 10:31:47
【问题描述】:

我有一个活动允许用户更改他的 UserPIN(Attendance_Records 表下的立即键),并且我已经读到除了删除和添加数据并再次更新之外,没有其他方法可以更新 Firebase 实时数据库.我的问题是我必须更新表中的键,但它有多个子键和大量数据。如何访问子密钥并存储它们?数据更新不会花很多时间吗?

假设我必须更新密钥:123452

出勤记录表

除了我在下面尝试过的以外,如果还有其他方法,我会全力以赴

编辑

我已经达到了可以使用以下方法从 Attendance_Records 表中检索数据的级别:

rootRefAttTable = FirebaseDatabase.getInstance()
                                  .getReference("Attendance_Records")
                                  .child(carriedmPIN);
newRefAttTable = FirebaseDatabase.getInstance()
                                 .getReference("Attendance_Records");
attRec = new Attendance_Records();

然后

private void changeAttTable(){
Log.d("abcd","changeAttTable() reached");

rootRefAttTable.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
            if(dataSnapshot.exists()){

            for(DataSnapshot yearsnap:dataSnapshot.getChildren()){
                yearKey = yearsnap.getKey();
                Log.d("abcd","yearKey is: "+yearKey);

                monthkeyRef = rootRefAttTable.child(yearKey);
                monthkeyRef.addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        if(dataSnapshot.exists()){
                            for(DataSnapshot monthsnap:dataSnapshot.getChildren()){
                                monthKey = monthsnap.getKey();

                                datekeyRef = monthkeyRef.child(monthKey);
                                datekeyRef.addListenerForSingleValueEvent(new ValueEventListener() {
                                    @Override
                                    public void onDataChange(DataSnapshot dataSnapshot) {
                                        if(dataSnapshot.exists()){

                                            for(DataSnapshot datesnap:dataSnapshot.getChildren()){
                                                dateKey = datesnap.getKey();


                                                date = datesnap.child("date").getValue(String.class);
                                                enteryDate = datesnap.child("entryDate").getValue(String.class);
                                                inTime = datesnap.child("inTime").getValue(String.class);
                                                month = datesnap.child("month").getValue(String.class);
                                                myID = datesnap.child("myID").getValue(String.class);
                                                outTime = datesnap.child("outTime").getValue(String.class);
                                                status = datesnap.child("status").getValue(String.class);
                                                year = datesnap.child("year").getValue(String.class);

                                                addDataAttTable();
                                            }
                                        }
                                    }

                                    @Override
                                    public void onCancelled(DatabaseError databaseError) {

                                    }
                                });
                            }
                        }
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {

                    }
                });

            }
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {

    }
});
}

private void getValuesAtt(){
Log.d("abcd","getValuesAtt() reached");

attRec.setYear(year);
attRec.setMonth(month);
attRec.setMyID(myID);
attRec.setEntryDate(enteryDate);
attRec.setStatus(status);
attRec.setOutTime(outTime);
attRec.setInTime(inTime);
attRec.setDate(date);
}

private void addDataAttTable(){
Log.d("abcd","addDataAttTable() reached");

getValuesAtt();
newRefAttTable.child(carriedmPIN).removeValue();
newRefAttTable.child(enterednewmpin).child(yearKey).child(monthKey).child(dateKey).setValue(attRec);
}

但是,添加到数据库的方式并没有按照应有的方式进行:

之前

之后

抱歉更新前的图片。更新后(123450 到 123459),第 3 个月和第 4 个月合并在一起,现在我没有 2 年(假设是 2018 年和 2019 年),否则我认为他们也会加入。我该如何纠正这个问题?

【问题讨论】:

    标签: java android firebase firebase-realtime-database


    【解决方案1】:

    我终于做到了!

    有时您会考虑更深层次的逻辑,但所需的只是一个简单的代码!

    我是这样做的:

    rootRefAttTable = FirebaseDatabase.getInstance().getReference("Attendance_Records").child(carriedmPIN);
    
    newRefAttTable = FirebaseDatabase.getInstance().getReference("Attendance_Records");
    

    carriedmPIN 是用户需要更改的 PIN 码。

    private void changeAttTable() {
    
        Log.d("abcd","changeAttTable() reached");
    
         rootRefAttTable.addListenerForSingleValueEvent(new ValueEventListener() {
             @Override
             public void onDataChange(DataSnapshot dataSnapshot) {
                 for(DataSnapshot yearsnap:dataSnapshot.getChildren()){
                    for(DataSnapshot monthsnap:yearsnap.getChildren()){
                        for(DataSnapshot datesnap:monthsnap.getChildren()){
                            dateAtt = datesnap.child("date").getValue(String.class);
                            Log.d("abcd","date is: "+dateAtt);
                            entrydateAtt = datesnap.child("entryDate").getValue(String.class);
                            Log.d("abcd","enteryDate is: "+entrydateAtt);
                            intimeAtt = datesnap.child("inTime").getValue(String.class);
                            Log.d("abcd","inTime is: "+intimeAtt);
                            monthAtt = datesnap.child("month").getValue(String.class);
                            Log.d("abcd","month is: "+monthAtt);
                            myidAtt = datesnap.child("myID").getValue(String.class);
                            Log.d("abcd","myID is: "+myidAtt);
                            outtimeAtt = datesnap.child("outTime").getValue(String.class);
                            Log.d("abcd","outTime is: "+outtimeAtt);
                            statusAtt = datesnap.child("status").getValue(String.class);
                            Log.d("abcd","status is: "+statusAtt);
                            yearAtt = datesnap.child("year").getValue(String.class);
                            Log.d("abcd","year is: "+yearAtt);
    
                            getValuesAtt();
                            newRefAttTable.child(enterednewmpin).child(yearsnap.getKey()).child(monthsnap.getKey()).child(datesnap.getKey()).setValue(attRec);
                        }
                    }
    
                 }
             newRefAttTable.child(carriedmPIN).removeValue();
             }
    
             @Override
             public void onCancelled(DatabaseError databaseError) {
    
             }
    
         });
    
    }
    
    private void getValuesAtt(){
        Log.d("abcd","getValuesAtt() reached");
    
        attRec.setYear(yearAtt);
        attRec.setMonth(monthAtt);
        attRec.setMyID(myidAtt);
        attRec.setEntryDate(entrydateAtt);
        attRec.setStatus(statusAtt);
        attRec.setOutTime(outtimeAtt);
        attRec.setInTime(intimeAtt);
        attRec.setDate(dateAtt);
    }
    

    我太高兴了!!我卡在这个问题上很久了!! :P

    【讨论】:

      【解决方案2】:

      我想这里的问题是 monthKey 很常见,如果我做对了,它是 04,所以默认情况下 Firebase 将其视为同一个子节点,并将添加所有内容。 p>

      但回到主要问题,更换别针,您是否尝试过这个:

      编辑: 您为什么不使用 Firebase 为添加的每个孩子提供的唯一 id 并将其用作键来更改数据库的结构,然后在您的孩子中为 pin 添加一个字段?

      首先,如果您的用户具有共同的 PIN,这将首先确保您的所有孩子以后不会发生冲突,其次,它将更容易检索临时对象上的整个用户对象,更改 PIN 值在其中,然后使用提供的唯一 ID 再次将其推送给同一个孩子!

      如果您想知道如何获取此唯一 ID,我还建议您将其保存为对象中的字段,在推送对象时保存它,并在需要时从检索到的临时对象中检索。

      处理这一切的最佳方法是通过onChildAddedonChildChanged 方法而不是手动(提示: 尝试将您的数据库拆分为不同的引用,这将更容易你来管理ChildListener)

      【讨论】:

      • 我认为直接使用 setValue 是行不通的,因为它最多只是重命名我的密钥,所有的孩子都会被删除。
      • 是的,我刚刚检查过了,我确信有办法只是改变一个特定的值,或者改变数据库结构,比如将 pin 保存为对象中的一个字段?跨度>
      • 嘿!我之前检查过,在 Firebase 中无法重命名任何内容,我们需要删除并重新设置该值。对于不太复杂的数据库很容易做到,但我的有多个级别:/
      • 我无法更改数据库结构,因为仅根据此 PIN,我让用户每月查看他们的出勤率。
      • [此视频系列] (youtube.com/…) 应该阐明一个想法,即当涉及到 NoSQL DB 时,您需要转向扁平结构,希望它会有所帮助!但是,在您的情况下,如果您坚持按原样保存结构,我想通过添加您的 PIN 字段并使用提供的 Firebase 密钥,您可以在onChildAddded 中提取 PIN 和密钥列表,然后通过用户输入 PIN,您可以使用链接到它的密钥从数据库中获取您的对象。 (我仍然认为您需要考虑 PIN 码重复)
      猜你喜欢
      • 2021-12-31
      • 2014-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多