web-dev-qa-db-fra.com

Afficher les articles dans l'ordre affiché décroissant

J'essaie de tester Firebase pour permettre aux utilisateurs de poster des commentaires en utilisant Push. Je veux afficher les données que je récupère avec ce qui suit:

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

Le problème est que les données sont renvoyées dans l’ordre le plus ancien au plus récent; Est-ce que Firebase peut faire ça?

36
user2912591

Depuis que cette réponse a été écrite, Firebase a ajouté une fonctionnalité permettant de classer par enfant ou par valeur. Donc, il existe maintenant quatre façons de commander des données: par clé, par valeur, par priorité ou par la valeur de tout enfant nommé. Voir cet article de blog qui présente les nouvelles fonctionnalités de commande .

Les approches de base restent les mêmes cependant:

1. Ajoutez une propriété enfant avec l'horodatage inversé, puis commandez-la.

2. Lisez les enfants dans l'ordre croissant, puis inversez-les sur le client.

Firebase prend en charge la récupération des nœuds enfants d'une collection de deux manières:

  • de nom
  • par priorité

Ce que vous obtenez maintenant est un nom, qui se trouve être chronologique. Ce n'est pas un hasard si: lorsque vous Push un élément dans une collection, le nom est généré pour garantir que les enfants sont classés de cette manière. Pour citer la documentation Firebase pour Push :

Le nom unique généré par Push () est préfixé par un horodatage généré par le client afin que la liste résultante soit triée de manière chronologique.

Le Guide Firebase sur les données ordonnées a ceci à dire sur le sujet:

Comment les données sont commandées

Par défaut, les enfants d'un nœud Firebase sont triés lexicographiquement par nom. L'utilisation de Push() peut générer des noms d'enfants qui trieront naturellement par ordre chronologique, mais de nombreuses applications exigent que leurs données soient triées d'une autre manière. Firebase permet aux développeurs de spécifier l'ordre des éléments dans une liste en spécifiant une priorité personnalisée pour chaque élément.

Le moyen le plus simple d'obtenir le comportement souhaité consiste à spécifier également une priorité toujours décroissante lorsque vous ajoutez l'élément:

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

Mettre à jour

Vous devrez également récupérer les enfants différemment:

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

Dans mon test, utiliser on('child_added' garantit que les derniers enfants ajoutés sont renvoyés dans l'ordre chronologique inverse. Par contre, en utilisant on('value', les renvoie dans l'ordre de leur nom.

Assurez-vous de lire la section "Lecture des données ordonnées" , qui explique l'utilisation des événements child_* pour récupérer des enfants (ordonnés).

Un bin pour le démontrer: http://jsbin.com/nonawe/3/watch?js,console

41
Frank van Puffelen

Depuis firebase 2.0.x, vous pouvez utiliser limitLast() pour y parvenir:

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
}

Voici un lien vers l'annonce: Davantage de fonctionnalités d'interrogation dans Firebase

11
Maksymilian Majer

Il n'y a vraiment aucun moyen mais semble que nous avons le recyclage nous pouvons avoir cette 

 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

J'ai une date variable (long) et je voulais garder les articles les plus récents en haut de la liste. Alors ce que j'ai fait était:

  • Ajouter un nouveau champ long 'dateInverse'
  • Ajoutez une nouvelle méthode appelée 'getDateInverse', qui renvoie simplement: Long.MAX_VALUE - date;
  • Créer ma requête avec: .orderByChild ("dateInverse")
  • Presto! : p
3
Spoetnic

Vous recherchez limitTolast (Int x). Cela vous donnera les derniers "x" éléments supérieurs de votre base de données (ils sont classés par ordre croissant), mais il s'agit des "x" éléments supérieurs

si vous avez dans votre base de données {10 300,150,240,2,24,220}

cette méthode:

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

vous recopierons: {150,220,240,300}

3

Dans Android, il existe un moyen d'inverser réellement les données dans un tableau d'objets à l'aide de l'adaptateur. Dans mon cas, je ne pouvais pas utiliser LayoutManager pour inverser les résultats dans l'ordre décroissant, car j'utilisais une vue de recyclage horizontale pour afficher les données. La définition des paramètres suivants dans Recyclerview a gâché mon expérience d'interface utilisateur:

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

Le seul moyen efficace que j'ai trouvé à ce propos était d'utiliser la méthode BindViewHolder de l'adaptateur RecyclerView:

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

J'espère que cette réponse aidera tous les développeurs qui sont aux prises avec ce problème dans Firebase.

3
Michele La Ferla

Firebase: Comment afficher un fil d’éléments dans l’ordre inverse avec une limite pour chaque demande et un indicateur pour un bouton "Charger plus".

  • Cela va obtenir les 10 derniers éléments de la liste

FBRef.child ("ChildName") .limitToLast (loadMoreLimit) // loadMoreLimit = 10 par exemple

  • Cela va obtenir les 10 derniers articles. Saisissez l'id du dernier enregistrement de la liste et enregistrez pour le chargement plus de fonctionnalités. Ensuite, convertissez la collection d'objets en un tableau et effectuez une commande list.reverse (). 

  • LOAD MORE Fonctionnalité: le prochain appel fera deux choses: il obtiendra la prochaine séquence d'éléments de liste en fonction de l'ID de référence de la première demande et vous indiquera si vous devez afficher le bouton "charger plus". 

this.FBRef .child ("childName") .endAt (null, lastThreadId) // Extrait ceci de l'étape précédente .limitToLast (loadMoreLimit + 2)

  • Vous devrez supprimer le premier et le dernier élément de cette collection d'objets. Le premier élément est la référence pour obtenir cette liste. Le dernier élément est un indicateur pour le bouton Afficher plus. 

  • J'ai un tas d'autres logiques qui vont tout garder propre. Vous devrez ajouter ce code uniquement pour charger plus de fonctionnalités.

      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

J'utilise ReactFire pour une intégration facile de Firebase.

Fondamentalement, cela m’aide à stocker les données dans l’état du composant, sous la forme array. Ensuite, tout ce que je dois utiliser est la fonction reverse() ( en savoir plus )

Voici comment je réalise ceci:

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

Il y a un meilleur moyen. Vous devriez commander par horodatage négatif du serveur. Comment obtenir un horodatage négatif du serveur, même hors ligne? Il y a un champ caché qui aide. Extrait associé de la documentation:

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

Pour ajouter à la réponse de Dave Vávra, j’utilise un horodatage négatif comme étant mon sort_key like so

Réglage

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

Obtenir

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

Ceci récupère tous les objets du plus récent au plus ancien. Vous pouvez également $indexOn la sortKey pour le rendre encore plus rapide

1
Kurai Bankusu

J'ai eu ce problème aussi, j'ai trouvé une solution très simple à ce problème qui n'implique aucune manipulation des données. Si vous restituez le résultat dans le DOM, dans une liste quelconque. Vous pouvez utiliser flexbox et configurer une classe pour inverser les éléments de leur conteneur. 

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

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

0
PHILL BOOTH

Vous pouvez ajouter une colonne appelée orderColumn où vous gagnez du temps en tant que

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

save save Long order dans la colonne nommée orderColumn et lorsque vous récupérerez des données.

0
Parvesh Monu

Je l'ai fait par avance.

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

utilisez simplement reverse() sur le tableau, supposez que si vous stockez les valeurs dans un tableau items[], faites un this.items.reverse()

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

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

        this.items.Push(snapshot);

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

Quelqu'un a souligné qu'il y avait 2 façons de faire cela: 

  1. Manipuler les données côté client
  2. Faire une requête qui va commander les données

Pour ce faire, le moyen le plus simple consiste à utiliser l'option 1, mais à l'aide d'une variable LinkedList. Je viens d'ajouter chaque objet à l'avant de la pile. Il est suffisamment souple pour autoriser la liste à être utilisée dans ListView ou RecyclerView. De cette façon, même s’ils arrivent du plus ancien au plus récent, vous pouvez toujours afficher ou récupérer du plus récent au plus ancien. 

0
BlackHatSamurai