如何仅在firebase中获取子键

时间:2017-06-15 07:34:24

标签: java android json firebase firebase-realtime-database

Firebase database

我想只展示位置的儿童,即信德和旁遮普(不是他们的孩子)。是否可能,如果可以,我该怎么做?

8 个答案:

答案 0 :(得分:9)

来自文档中的Best practices for data structure

  

避免嵌套数据

     

因为Firebase实时数据库允许最多嵌套数据32   水平很深,你可能会想到这应该是   默认结构。但是,当您在您的位置获取数据时   数据库,您还检索其所有子节点。另外,什么时候   您在数据库中的某个节点上授予某人读取或写入权限   还授予他们访问该节点下的所有数据的权限。因此,在   实践中,最好保持数据结构尽可能平坦。

这就是Firebase的工作原理:如果你得到一件物品,你也可以得到它的孩子。如果你不想要这个,你应该重组数据库。

答案 1 :(得分:6)

  

避免嵌套数据

     

由于Firebase实时数据库允许最多嵌套数据深度为32级,因此您可能会认为这应该是默认结构。但是,当您在数据库中的某个位置获取数据时,还会检索其所有子节点。此外,当您在数据库中的某个节点上授予某人读取或写入权限时,您还可以授予他们访问该节点下所有数据的权限。因此,在实践中,最好保持数据结构尽可能平坦。

以下是您的如何实现平面数据库以及如何检索位置密钥的结构。

{
  "location": {
    "punjab": {
      "lahore": true,
      "multan": true
    },
    "sindh": {
      "karachi": true
    }
  },

  "place": {
    "lahore": {
      "location": "punjab",
      "details": {
        "0": "model",
        "1": "steel town"
      }
    },
    "multan": {
      "location": "punjab",
      "contacts": {
        "0": "myarea"
      }
    },
    "karachi": {
      "location": "sindh",
      "contacts": {
        "0": "hadeed",
        "1": "Steel town"
      }
    }
  }
}

以下是可用于检索位置密钥的代码。

private DatabaseReference mDatabase;
// ...
mDatabase = FirebaseDatabase.getInstance().getReference();
mLocation = mDatabase.child("location");
mPlace = mDatabase.child("place");

ValueEventListener placeListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        // Get Post object and use the values to update the UI
        Place place = dataSnapshot.getValue(Place.class);
        String location = place.location;
        System.out.println(location);
    }
};
mPlace.addValueEventListener(placeListener);

有关Firebase的详细信息:

答案 2 :(得分:1)

是的,你可以

ValueEventListener getValueListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
    // Get data from firebase
    Log.d("The name of child that you need:", dataSnapshot.getKey());
    // ...
}

};

databaseReference.addValueEventListener(getValueListener );

了解详情:https://firebase.google.com/docs/database/android/read-and-write#listen_for_value_events

答案 3 :(得分:1)

虽然不建议在像Firebase这样的NoSQL数据库中嵌套数据,但要获取子节点的名称,您的代码将如下所示

DatabaseReference mainRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference locationref = mainRef.child("location");
final ArrayList<String> locationNames = new ArrayList<>();
locationref.addChildEventListener(new ChildEventListener() {
    @Override
    public void onChildAdded(DataSnapshot dataSnapshot, String s) {
        locationNames.add(dataSnapshot.getKey());
    }

    @Override
    public void onChildChanged(DataSnapshot dataSnapshot, String s) {

    }

    @Override
    void onChildRemoved(DataSnapshot dataSnapshot) {

    }

    @Override
    public void onChildMoved(DataSnapshot dataSnapshot, String s) {

    }

    @Override
    public void onCancelled(DatabaseError databaseError) {

    }
});

您现在可以使用locationNames执行您想要的操作。

答案 4 :(得分:1)

DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference().child("location");

final ArrayList<String> statesArrayList= new ArrayList<>();

databaseReference.addChildEventListener(new ChildEventListener() {

    @Override
    public void onChildAdded(DataSnapshot dataSnapshot, String s) {
        statesArrayList.add(dataSnapshot.getKey());
    }

    @Override
    public void onChildChanged(DataSnapshot dataSnapshot, String s) {

    }

    @Override
    void onChildRemoved(DataSnapshot dataSnapshot) {

    }

    @Override
    public void onChildMoved(DataSnapshot dataSnapshot, String s) {

    }

    @Override
    public void onCancelled(DatabaseError databaseError) {

    }
});

答案 5 :(得分:0)

Firebase可以快速查找级别1的节点,因为它可以在级别32处查找。深度不是影响技术级别速度的因素,但多年使用Firebase的经验表明深层嵌套数据通常是齐头并进的有性能问题。例如,我重新阅读了您正在阅读的官方文档Best practices for data structure in FirebaseStructuring your Firebase Data correctly for a Complex App

如果您不想更改实际的数据库结构并假设location节点是Firebase root的直接子节点,请参阅以下代码:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference locationRef = rootRef.child("location");
ValueEventListener eventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for(DataSnapshot ds : dataSnapshot.getChildren()) {
            String key = ds.getKey();
            Log.d("TAG", key);
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {}
};
locationRef.addListenerForSingleValueEvent(eventListener);

您的输出将是:

punjab
sindh

答案 6 :(得分:0)

我知道这个问题是在不久前针对Android平台问的,但是我一直在寻找解决方案,因此遇到了这个问题。我无法使用提供的答案,所以这是我找到的解决方案。这样只会得到孩子,别无其他。

这是用javascript编写的,但是您可以使用Java中的另一种方法来从REST端点发出请求。

const databaseURL = "https://example.firebaseio.com" // replace value with yours
const endpoint = "location"
const user = firebase.auth().currentUser
user.getIdToken()
  .then(token => {
    return fetch(`${databaseURL}/${endpoint}.json?auth=${token}&shallow=true`)
  })
  .then(response => {
    return response.json()
  })
  .then(json => {
    console.log({json}) // contains only the children
  })
  .catch(error => {
    console.log(error.message)
  })

这里重要的一点是&shallow=true,否则您将在子节点中获取所有数据。

使用卷发

curl 'https://example.firebaseio.com/location.json?auth=INSERT_TOKEN&shallow=true'

这假设location是根的子代。

通过查看docs

可以获得更多详细信息

在调用此功能之前,必须确保Firebase中有currentUser。

此外,我会留意此处提到的有关适当的Firebase实时数据库结构的警告。但是,如果您已经在这个位置,那么可以提供帮助。

答案 7 :(得分:-1)

这就是你如何获得孩子名字

HashMap<String, Object> allData = (HashMap<String, Object>) dataSnapshot.getValue();
String[] yourChildArray = allData.keySet().toArray(new String[0]);