Firebase Database Struktur/Redundanz/Voting

  • Antworten:3
Hans Cluedo
  • Forum-Beiträge: 17

26.07.2018, 11:55:38 via Website

Hey Leute,

habe einmal ein paar Fragen zur Firebase Database. Hoffentlich könnt ihr mir helfen.

  1. Meine Database in Firebase erstellt immer einen Zeitstempel wenn ich einen Eintrag hinzufüge. Kann man das nicht auch ohne Zeitstempel erstellen?

Hier mal mein Code:

public class FirebaseHelper {

DatabaseReference db;
String modelName;
Boolean saved=null;

public interface MyCallback {
    void onCallback(ArrayList<String> value);
}

public FirebaseHelper(DatabaseReference db, String modelName) {
    this.db = db;
    this.modelName = modelName;
}

//SAVE
public  Boolean save(Words words)
{
    if(words ==null)
    {
        saved=false;
    }else
    {
        try
        {
            db.child(modelName).push().setValue(words);
            saved=true;
        }catch (DatabaseException e)
        {
            e.printStackTrace();
            saved=false;
        }
    }

    return saved;
}

//READ
public void retrieve(final MyCallback myCallback)
{

    db.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {
            myCallback.onCallback(fetchData(dataSnapshot));
        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {
            myCallback.onCallback(fetchData(dataSnapshot));
        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {

        }

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

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

}

private ArrayList<String> fetchData(DataSnapshot snapshot)
{
    ArrayList<String> spacecrafts = new ArrayList<>();
    for (DataSnapshot ds:snapshot.getChildren())
    {
        String name=ds.getValue(Words.class).getName();
        spacecrafts.add(name);

    }
    return spacecrafts;
}

}

Mit dieser Methode wird der Eintrag gespeichert:

private void displayInputDialog(final MainActivity.Type selectedType) {
    Dialog d=new Dialog(this);
    d.setTitle("Firebase Database");
    d.setContentView(R.layout.output_layout);

    String name=out.getText().toString();

    Words s = new Words();
    s.setName(name);

    //SAVE
    if (name != null && name.length() > 0) {
        switch (selectedType) {
            case WORD: {
                if (helper3.save(s)) {
                    Toast.makeText(MainActivity.this, name + " added successfully\nto the database",
                            Toast.LENGTH_SHORT).show();
                }
                break;
            }
        }
    } else {
        Toast.makeText(MainActivity.this, "Word Cannot Be Empty", Toast.LENGTH_SHORT).show();
    }

}

Und hier dann die Database Struktur die erstellt wird.

{

"1stWord" : {
"1stWord" : {
"-LI125GLPy0-IPAm4GEM" : {
"name" : "test"
},

und so weiter. Beziehungsweise, kann man das noch "schöner", ordentlicher aufbauen/strukturieren?

  1. Habe eine App, die aus zwei Wörtern ein neues Wort generieren soll.
    Es stehen also zwei Datenbankeinträge bereit und es wird ein neuer erstellt, wenn man zwei Einträge eben zusammenfügt. Das neue Wort hat dann wieder die gleiche Datenbankstruktur wie das "1stWord" oben zeigt.
    So. Geht das irgendwie, dass man dann das neu-generierte Wort bewerten kann. Also eben Daumen hoch oder Daumen runter, dass es direkt unter dem Datenbankeintrag gespeichert wird, um danach eine Rankingliste zu erstellen?
    Also das die Struktur dann so aussieht:

    {
    "NewWord" : {
    "NewWord" : {
    "-LI125GLPy0-IPAm4GEM" : { (Am Besten ohne den Zeitstempel?)
    "name" : "testlauf": {
    "voteup" : 1,
    "votedown" : 0
    },

Für jeden Daumen hoch/runter wird der Eintrag eben um eins erhöht und nachher kann man dann die Rankingliste erstellen. Welches Wort eben die meisten Voteups hat, steht oben und so weiter.

  1. Wie kann man Redundanzen vermeiden? Habe zwar schon einen Code dazu, aber irgendwie funktioniert das durch die Zeitstempel nicht so wirklich.

Code:

String txt1 = text1.getText().toString();
            String txt2 = text2.getText().toString();
            out.setText(txt1 + txt2);
            final String outta = txt1 + txt2;

            db3.child("Newword").orderByChild("Newword").equalTo(**was kommt hier rein? also wie greife ich dort auf die komplette Datenbank zu? **).addValueEventListener(new ValueEventListener(){
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    if(dataSnapshot.exists()){
                        Toast.makeText(getApplicationContext(), "Word already exist", Toast.LENGTH_SHORT).show();
                    } else {
                        displayInputDialog(Type.Newword);
                        Intent intent = new Intent(MainActivity.this, GenWord.class);
                        intent.putExtra("message", outta);
                        startActivity(intent);
                    }
                }

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

Der code sollte ja funktionieren?

  1. Fast gleiche Frage wie die Nr. 2. Kann man einen Locationeintrag erstellen, in der man wie oben auch Daumen hoch/runter eintragen kann?
    Also wenn jetzt einer aus Berlin eine Sache toll findet, dann soll es für den Locationeintrag "Berlin" eben ein "voteup" geben. Wenn ein anderer aus Berlin auch eine Sache toll findet, dann wird es um 1 erhöht und so weiter. Wenn jemand aus einem kleinen Dorf eine Sache schlecht findet gibts ein votedown. Ist das möglich, oder wäre das viel zu viel (da ja jede Location, also auch das letzte Dort der Welt in Frage kommen würde) für die Datenbank?

Ich hoffe, dass ich die Fragen verständlich rüber bringen konnte und das ihr ein paar Tipps habt.
Bin euch jetzt schon einmal sehr dankbar! :)

Noch einen schönen Tag.

Antworten
swa00
  • Forum-Beiträge: 3.704

26.07.2018, 12:03:23 via Website

Hallo Hans ,

ich bin natürlich nicht deinen Code ins Detail durchgegangen - das würde auch eine Forenhilfe sprengen.

Grundsätzlich bin ich allerdings verwirrt bei deiner Frage nach dem DB Eintrag.

Dies wäre schlichtweg mit einem numerischen Feld in einer Umkreis-Location zu realisieren.
Dazu solltest du Lat/Lon auswerten , einen Umkreis bilden und eine entsprechende Inbound Tabelle mitführen.

Das Ganze hat aber nichts mit Firebase zu tun (ich würde eh was Anders nehmen) , sondern mit deiner Inbound Berechnungslogik.

— geändert am 26.07.2018, 12:15:02

Liebe Grüße - Stefan
[ App - Entwicklung ]

Hans Cluedo

Antworten
Jokel
  • Forum-Beiträge: 1.530

26.07.2018, 18:44:22 via Website

Hallo ich habe auch das gefühlt das eine vernünftige Erklärung zu viel für das Frorum sein wird.
Denke du hast das Prinzip der Objekt Datenbank Firebase noch nicht verstanden.
Firebase arbeitet und Speichert alles im Json Format.
Kommt mir so vor als ob du damit deine Probleme hast.

Vielleicht ist es für dich einfacher eine relationale Datenbank zu benutzen und keine Objektorientierte . dort kannst du es wie gewohnt in Tabellen speichern.

Zu deinem Code.

Dieser "-LI125GLPy0-IPAm4GEM" Zeitstempel wie du sagst entsteht eigentlich wenn du ein Child Element erstellst und keinen Bezeichner eingibst.
Kann auch sein das du beim schreiben in deine Child Objekt und nur dem unter Objekt einen Namen gegeben hast und da erstellt Firebase solche Sachen . Arbeite etwas sauberer.

Locationeintrag da es in eine ODB keine Tabellen gibt würde ich die Städte in in einem ArrayObjekt speichern . Bei einer relationalen DB würde ich eine neue Tabelle machen.

Du musst dir erst mal eine sinnvolle Json Struktur ausdenken . In die du alles Speichern kannst.
Bei einer Tabelle würdest du dir auch gedankten über die Struktur machen und nicht einfach drauf los Programmieren. Dann weist du auch welche Referenzen du brauchst.

Auch sinnvoll ist es Parser zu benutzen um die Objekte zu erstellen und auch zu Speichern.

Bei einer ODB brauchst du dir keine gedenken über Redundanzen machen .
Eine ODB ist ohnehin eigent lich nur für wenig Daten gedacht bei grossen Daten mengen sind die Relationalen den ODB überlegen.
Redundanzen: kümmere dich erst mal nicht darum, bekomme erst mal den Ablauf in griff bevor du dich damit beschäftigst.

Hier ein Video was die Struktur etwas erklärt.

https://www.youtube.com/watch?v=iAvQFlhyvvQ

Wie sieht eigentlich der String „modelName“ aus ?

Mit “db.child(modelName).push().setValue(words);” speicherst du immer wider alles auf die gleiche Reverenz also deine modelName so wird sie immer wieder mit neuen Wörtern über schrieben. Du musst deine Reverenz auch weiter setzen.

Was ist eigentlich „helper3.save(s)“ ?
Was ist die Klasse Words ?
Worauf zeigt deine Reverenz?

— geändert am 26.07.2018, 20:05:53

Hans Cluedo

Antworten
Hans Cluedo
  • Forum-Beiträge: 17

26.07.2018, 20:39:49 via Website

Hi Stefan und Jokel,

danke für eure Antworten!

Hallo Hans ,

ich bin natürlich nicht deinen Code ins Detail durchgegangen - das würde auch eine Forenhilfe sprengen.

Grundsätzlich bin ich allerdings verwirrt bei deiner Frage nach dem DB Eintrag.

Dies wäre schlichtweg mit einem numerischen Feld in einer Umkreis-Location zu realisieren.
Dazu solltest du Lat/Lon auswerten , einen Umkreis bilden und eine entsprechende Inbound Tabelle mitführen.

Das Ganze hat aber nichts mit Firebase zu tun (ich würde eh was Anders nehmen) , sondern mit deiner Inbound Berechnungslogik.

Die ganzen Codes waren wohl zu viel ja :D Dachte, dass es dadurch einfacher wird. Das war wohl falsch.

Werde mich wohl einmal durch das Internet stöbern und nach einer Alternative schauen.

@Jokel

Ja, komm damit nicht so klar. Habe halt ein bisschen im Internet geschaut und dann die Codeschnipsel zusammengetragen :D Es funktioniert soweit auch (bis auf die Fragen eben), aber so macht das dann ja keinen Sinn.

Danke für die vielen Tipps. Werde ich mir zu Herzen nehmen!

Wenn ich noch Fragen habe, kann ich diese ja bestimmt stellen :P

Antworten