webentwicklung-frage-antwort-db.com.de

Beiträge in absteigender Reihenfolge anzeigen

Ich versuche, Firebase auszuprobieren, damit Benutzer Kommentare mit Push veröffentlichen können. Ich möchte die Daten anzeigen, die ich mit den folgenden Informationen abruft.

fbl.child('sell').limit(20).on("value", function(fbdata) { 
  // handle data display here
}

Das Problem ist, dass die Daten in der Reihenfolge vom ältesten zum neuesten zurückgegeben werden - ich möchte es in umgekehrter Reihenfolge. Kann Firebase das tun?

36
user2912591

Da diese Antwort bereits geschrieben wurde, hat Firebase eine Funktion hinzugefügt, die die Bestellung nach einem Kind oder nach Wert ermöglicht. Es gibt nun vier Möglichkeiten, Daten zu bestellen: nach Schlüssel, nach Wert, nach Priorität oder nach dem Wert eines beliebigen Namens Siehe diesen Blogbeitrag, der die neuen Bestellmöglichkeiten vorstellt .

Die grundlegenden Ansätze bleiben jedoch gleich:

1. Fügen Sie eine untergeordnete Eigenschaft mit dem umgekehrten Zeitstempel hinzu und ordnen Sie danach die Reihenfolge an.

2. Lesen Sie die Kinder in aufsteigender Reihenfolge und invertieren Sie sie auf dem Client.

Firebase unterstützt das Abrufen untergeordneter Knoten einer Sammlung auf zwei Arten:

  • namentlich
  • vorrangig

Was Sie jetzt bekommen, ist der Name, der zufällig chronologisch ist. Das ist übrigens kein Zufall: Wenn Sie ein Element in eine Sammlung Push eingeben, wird der Name generiert, um sicherzustellen, dass die untergeordneten Elemente auf diese Weise bestellt werden. So zitieren Sie die Firebase-Dokumentation für Push :

Dem von Push () generierten eindeutigen Namen wird ein vom Client generierter Zeitstempel vorangestellt, sodass die Ergebnisliste chronologisch sortiert wird.

Der Firebase-Leitfaden zu bestellten Daten hat dazu folgendes zu sagen:

Wie werden Daten bestellt?

Kinder in einem Firebase-Knoten werden standardmäßig lexikographisch nach Namen sortiert. Mit Push() können untergeordnete Namen generiert werden, die natürlich chronologisch sortiert werden. In vielen Anwendungen müssen die Daten jedoch auf andere Weise sortiert werden. Mit Firebase können Entwickler die Reihenfolge der Elemente in einer Liste festlegen, indem für jedes Element eine benutzerdefinierte Priorität festgelegt wird.

Die einfachste Möglichkeit, das gewünschte Verhalten zu erhalten, besteht darin, beim Hinzufügen des Elements auch eine immer abnehmende Priorität anzugeben:

var ref = new Firebase('https://your.firebaseio.com/sell');
var item = ref.Push();
item.setWithPriority(yourObject, 0 - Date.now());

Aktualisieren

Sie müssen die Kinder auch anders abrufen:

fbl.child('sell').startAt().limit(20).on('child_added', function(fbdata) {
  console.log(fbdata.exportVal());
})

In meinem Test mit on('child_added' wird sichergestellt, dass die zuletzt hinzugefügten Kinder in umgekehrter chronologischer Reihenfolge zurückgegeben werden. Wenn Sie jedoch on('value' verwenden, werden sie in der Reihenfolge ihres Namens zurückgegeben.

Lesen Sie unbedingt den Abschnitt Abschnitt "Lesen der geordneten Daten" , der die Verwendung der child_*-Ereignisse zum Abrufen von (geordneten) untergeordneten Elementen erläutert.

Ein Behälter, um dies zu demonstrieren: http://jsbin.com/nonawe/3/watch?js,console

41

Seit firebase 2.0.x können Sie limitLast() verwenden, um dies zu erreichen:

fbl.child('sell').orderByValue().limitLast(20).on("value", function(fbdataSnapshot) { 
  // fbdataSnapshot is returned in the ascending order
  // you will still need to order these 20 items in
  // in a descending order
}

Hier ist ein Link zur Ankündigung: Weitere Abfragefunktionen in Firebase

11

Um Franks Antwort zu ergänzen, können Sie auch die neuesten Datensätze abrufen, auch wenn Sie sich nicht die Mühe gemacht haben, sie nach Prioritäten zu ordnen. Verwenden Sie dazu einfach endAt().limit(x) demo:

var fb = new Firebase(URL);

// listen for all changes and update
fb.endAt().limit(100).on('value', update);

// print the output of our array
function update(snap) {
   var list = [];
    snap.forEach(function(ss) {
       var data = ss.val();
       data['.priority'] = ss.getPriority();
       data['.name'] = ss.name();
       list.unshift(data); 
    });
   // print/process the results...
}

Beachten Sie, dass dies sogar bis zu vielleicht tausend Datensätzen recht performant ist (vorausgesetzt, die Nutzlasten sind klein). Für robustere Verwendungen ist Franks Antwort maßgeblich und viel skalierbarer.

Diese rohe Gewalt kann auch optimiert werden, um mit größeren Daten oder mehr Datensätzen zu arbeiten, indem Dinge wie das Überwachen von child_added/child_removed/child_moved Ereignisse anstelle von value und Verwendung eines Entprellen , um DOM-Aktualisierungen in großen Mengen anstatt einzeln anzuwenden.

DOM-Aktualisierungen sind natürlich ein Stinker, unabhängig von der Herangehensweise, wenn Sie sich erst einmal mit Hunderten von Elementen befasst haben. Daher ist der Entprellungsansatz (oder eine React.js-Lösung, bei der es sich im Wesentlichen um eine übermäßige Entprellung handelt) ein großartiges Werkzeug.

7
Kato

Es gibt wirklich keinen Weg, aber es scheint, als hätten wir den Recycling-Überblick, den wir haben können 

 query=mCommentsReference.orderByChild("date_added");
        query.keepSynced(true);

        // Initialize Views
        mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
        mManager = new LinearLayoutManager(getContext());
//        mManager.setReverseLayout(false);
        mManager.setReverseLayout(true);
        mManager.setStackFromEnd(true);

        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setLayoutManager(mManager);
4
Goodlife

Ich habe eine Datumsvariable (lang) und wollte die neuesten Elemente oben auf der Liste behalten. Also was ich getan habe war:

  • Fügen Sie ein neues langes Feld 'dateInverse' hinzu.
  • Fügen Sie eine neue Methode mit dem Namen 'getDateInverse' hinzu, die Folgendes zurückgibt: Long.MAX_VALUE - date;
  • Meine Abfrage erstellen mit: .orderByChild ("dateInverse")
  • Presto! : p
3
Spoetnic

Sie suchen nach limitTolast (Int x). Dies gibt Ihnen die letzten "x" höheren Elemente Ihrer Datenbank (diese sind aufsteigend), aber sie sind die "x" höheren Elemente

wenn Sie in Ihre Datenbank aufgenommen haben {10,300,150,240,2,24,220}

diese Methode:

myFirebaseRef.orderByChild("highScore").limitToLast(4)

holt Sie ab: {150,220,240,300}

In Android gibt es eine Möglichkeit, die Daten in einer Arrayliste von Objekten über den Adapter tatsächlich umzukehren. In meinem Fall konnte ich den LayoutManager nicht verwenden, um die Ergebnisse in absteigender Reihenfolge umzukehren, da ich zur Anzeige der Daten einen horizontalen Recyclerview verwendet habe. Das Einstellen der folgenden Parameter für das Recycler hat meine Benutzeroberfläche beeinträchtigt:

llManager.setReverseLayout(true);
llManager.setStackFromEnd(true);

Die einzige Arbeitsweise, die ich in dieser Hinsicht gefunden habe, war die BindViewHolder-Methode des RecyclerView-Adapters:

@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
    final SuperPost superPost = superList.get(getItemCount() - position - 1);
}

Ich hoffe, diese Antwort wird allen Entwicklern helfen, die mit diesem Problem in Firebase zu kämpfen haben.

3

Firebase: Anzeigen eines Threads von Elementen in umgekehrter Reihenfolge mit einem Limit für jede Anforderung und einem Indikator für die Schaltfläche "Mehr laden".

  • Dadurch werden die letzten 10 Elemente der Liste angezeigt

FBRef.child ("childName") .limitToLast (loadMoreLimit) // loadMoreLimit = 10 zum Beispiel

  • Dadurch werden die letzten 10 Elemente angezeigt. Holen Sie sich die ID des letzten Datensatzes in der Liste und sparen Sie für das Laden mehr Funktionalität. Als nächstes konvertieren Sie die Objektgruppe in ein Array und führen Sie eine list.reverse () aus. 

  • LOAD MORE Functionality: Beim nächsten Aufruf werden zwei Aufgaben ausgeführt. Es wird die nächste Folge von Listenelementen basierend auf der Referenz-ID aus der ersten Anforderung abgerufen. Sie erhalten einen Hinweis, ob Sie die Schaltfläche "Mehr laden" anzeigen müssen. 

this.FBRef .child ("childName") .endAt (null, lastThreadId) // Holen Sie sich dies aus dem vorherigen Schritt .limitToLast (loadMoreLimit + 2)

  • Sie müssen das erste und letzte Element dieser Objektauflistung entfernen. Der erste Punkt ist die Referenz, um diese Liste zu erhalten. Das letzte Element ist ein Indikator für die Schaltfläche Mehr anzeigen. 

  • Ich habe eine Menge anderer Logik, die alles sauber hält. Sie müssen diesen Code nur für das Laden weiterer Funktionen hinzufügen.

      list = snapObjectAsArray;  // The list is an array from snapObject
      lastItemId = key; // get the first key of the list
    
      if (list.length < loadMoreLimit+1) {
        lastItemId = false; 
      }
      if (list.length > loadMoreLimit+1) {
        list.pop();
      }
      if (list.length > loadMoreLimit) {
        list.shift();
      }
      // Return the list.reverse() and lastItemId 
      // If lastItemId is an ID, it will be used for the next reference and a flag to show the "load more" button.
    }
    
2
Andrew Axelrod

Ich benutze ReactFire für die einfache Integration von Firebase.

Grundsätzlich hilft es mir, die Daten als array im Komponentenzustand zu speichern. Dann muss ich nur noch die Funktion reverse() ( read more ) verwenden.

So mache ich das:

import React, { Component, PropTypes } from 'react';
import ReactMixin from 'react-mixin';
import ReactFireMixin from 'reactfire';

import Firebase from '../../../utils/firebaseUtils'; // Firebase.initializeApp(config);

@ReactMixin.decorate(ReactFireMixin)
export default class Add extends Component {
    constructor(args) {
        super(args);

        this.state = {
            articles: []
        };
    }

    componentWillMount() {
        let ref = Firebase.database().ref('articles').orderByChild('insertDate').limitToLast(10);
        this.bindAsArray(ref, 'articles'); // bind retrieved data to this.state.articles
    }

    render() {
        return (
            <div>
                {
                    this.state.articles.reverse().map(function(article) {
                        return <div>{article.title}</div>
                    })
                }
            </div>
        );
    }
}
2
pistou

Es gibt einen besseren Weg. Sie sollten nach negativem Serverzeitstempel bestellen. Wie bekomme ich einen negativen Serverzeitstempel auch offline? Es gibt ein verstecktes Feld, das hilft. Zugehöriger Ausschnitt aus der Dokumentation:

var offsetRef = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/.info/serverTimeOffset");
  offsetRef.on("value", function(snap) {
  var offset = snap.val();
  var estimatedServerTimeMs = new Date().getTime() + offset;
});
1
David Vávra

Um Dave Vávras Antwort hinzuzufügen, verwende ich einen negativen Zeitstempel als meinen sort_key

Einstellung

const timestamp = new Date().getTime();
const data = {
  name: 'John Doe',
  city: 'New York',
  sort_key: timestamp * -1 // Gets the negative value of the timestamp
}

Bekommen

const ref = firebase.database().ref('business-images').child(id);
const query = ref.orderByChild('sort_key');
return $firebaseArray(query); // AngularFire function

Dadurch werden alle Objekte vom neuesten bis zum ältesten Objekt abgerufen. Sie können auch $indexOn die sortKey verwenden, um die Ausführung noch schneller zu machen

1
Kurai Bankusu

Ich hatte auch dieses Problem, ich fand eine sehr einfache Lösung, bei der die Daten nicht ohnehin manipuliert wurden. Wenn Sie das Ergebnis zum DOM rendern, in einer Art Liste. Sie können flexbox verwenden und eine Klasse einrichten, um die Elemente in ihrem Container umzukehren. 

.reverse {
  display: flex;
  flex-direction: column-reverse;
}
1
Darren

array.reverse (); oder this.items = items.map (item => item) .reverse ();

0
PHILL BOOTH

Sie können eine Spalte namens orderColumn hinzufügen, in der Sie Zeit sparen

Long refrenceTime = "large future time"; Long currentTime = "currentTime"; Long order = refrenceTime - currentTime;

speichern Sie jetzt Lange Reihenfolge in der Spalte orderColumn. Wenn Sie data abrufen.

0
Parvesh Monu

Ich habe dies durch Voranstellen getan.

query.orderByChild('sell').limitToLast(4).on("value", function(snapshot){
    snapshot.forEach(function (childSnapshot) {
        // PREPEND
    });
});
0
angel enanod

verwenden Sie einfach reverse() für das Array. Angenommen, Sie speichern die Werte in einem Array items[] und führen dann eine this.items.reverse() aus.

 ref.subscribe(snapshots => {
       this.loading.dismiss();

      this.items = [];
      snapshots.forEach(snapshot => {

        this.items.Push(snapshot);

      });
      **this.items.reverse();**
    },
0
Sajan Thomas

Jemand hat darauf hingewiesen, dass es zwei Möglichkeiten gibt, dies zu tun: 

  1. Manipulieren Sie die Daten clientseitig
  2. Machen Sie eine Abfrage, um die Daten zu ordnen

Die einfachste Möglichkeit, die ich gefunden habe, ist die Verwendung von Option 1, jedoch über eine LinkedList. Ich füge einfach jedes der Objekte an der Vorderseite des Stapels an. Es ist flexibel genug, um die Verwendung der Liste in einer ListView oder RecyclerView zuzulassen. Auf diese Weise können Sie, obwohl sie in der Reihenfolge vom ältesten zum neuesten kommen, immer das neueste zum ältesten anzeigen oder abrufen. 

0
BlackHatSamurai