Exibir postagens em ordem decrescente

Estou tentando testar o Firebase para permitir que os usuários postem comentários usando o push . Eu quero exibir os dados que eu recupero com o seguinte;

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

O problema é que os dados são retornados na ordem da mais antiga para a mais nova – eu quero isso em ordem inversa. O Firebase pode fazer isso?

Como essa resposta foi escrita, o Firebase adicionou um recurso que permite fazer pedidos por qualquer filho ou por valor. Portanto, agora há quatro maneiras de solicitar dados: por chave, por valor, por prioridade ou pelo valor de qualquer filho nomeado. Veja esta postagem do blog que apresenta os novos resources de pedidos .

As abordagens básicas continuam as mesmas:

1. Adicione uma propriedade filho com o carimbo de data / hora invertido e, em seguida, faça o pedido.

2. Leia as crianças em ordem crescente e depois inverta-as no cliente.

O Firebase suporta a recuperação de nós filhos de uma coleção de duas maneiras:

  • por nome
  • por prioridade

O que você está recebendo agora é pelo nome, o que acontece de ser cronológico. Isso não é coincidência btw: quando você push um item para uma coleção, o nome é gerado para garantir que as crianças sejam ordenadas dessa maneira. Para citar a documentação do Firebase para push :

O nome exclusivo gerado por push () é prefixado com um registro de data e hora gerado pelo cliente para que a lista resultante seja ordenada cronologicamente.

O guia do Firebase sobre dados ordenados tem isto a dizer sobre o tópico:

Como os dados são pedidos

Por padrão, os filhos em um nó do Firebase são classificados lexicograficamente por nome. O uso de push() pode gerar nomes de filhos que, naturalmente, ordenam cronologicamente, mas muitos aplicativos exigem que seus dados sejam classificados de outras maneiras. O Firebase permite que os desenvolvedores especifiquem a ordem dos itens em uma lista, especificando uma prioridade personalizada para cada item.

A maneira mais simples de obter o comportamento desejado é também especificar uma prioridade sempre decrescente quando você adiciona o item:

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

Atualizar

Você também terá que recuperar os filhos de maneira diferente:

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

No meu teste usando on('child_added' garante que os últimos poucos filhos adicionados sejam retornados em ordem cronológica inversa. Usando on('value' por outro lado, os retorna na ordem de seu nome).

Certifique-se de ler a seção “Lendo dados solicitados” , que explica o uso dos events child_* para recuperar filhos (ordenados).

Um bin para demonstrar isso: http://jsbin.com/nonawe/3/watch?js,console

Desde o firebase 2.0.x, você pode usar o limitLast() para conseguir isso:

 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 } 

Aqui está um link para o anúncio: mais resources de consulta no Firebase

Para aumentar a resposta de Frank, também é possível pegar os registros mais recentes – mesmo que você não tenha se incomodado em ordená-los usando prioridades – simplesmente usando endAt().limit(x) como esta 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... } 

Observe que isso é bastante eficiente, até talvez mil registros (supondo que as cargas sejam pequenas). Para usos mais robustos, a resposta de Frank é autoritária e muito mais escalável.

Essa força bruta também pode ser otimizada para trabalhar com dados maiores ou mais registros, fazendo coisas como monitorar child_added / child_removed / child_moved em vez de value e usando um debounce para aplicar atualizações DOM em massa em vez de individualmente.

As atualizações do DOM, naturalmente, são um tanto prejudiciais, independentemente da abordagem, assim que você entra nas centenas de elementos, a abordagem de debounce (ou uma solução React.js, que é essencialmente um debounce do uber) é uma ótima ferramenta para se ter.

Eu tenho uma variável de data (longa) e queria manter os itens mais novos no topo da lista. Então o que eu fiz foi:

  • Adicione um novo campo longo ‘dateInverse’
  • Adicione um novo método chamado ‘getDateInverse’, que apenas retorna: Long.MAX_VALUE – date;
  • Crie minha consulta com: .orderByChild (“dateInverse”)
  • Presto! : p

Você está pesquisando limitTolast (Int x). Isso lhe dará os últimos “x” elementos superiores do seu database (eles estão em ordem crescente), mas eles são os elementos “x” superiores

se você entrou em seu database {10,300,150,240,2,24,220}

este método:

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

vai te retribuir: {150,220,240,300}

Não há realmente nenhuma maneira, mas parece que temos a visão de recyclerview, podemos ter este

  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); 

Firebase: como exibir um segmento de itens em ordem inversa com um limite para cada solicitação e um indicador para um botão “carregar mais”.

  • Isto irá obter os últimos 10 itens da lista

FBRef.child (“childName”) .limitToLast (loadMoreLimit) // loadMoreLimit = 10 por exemplo

  • Isto irá obter os últimos 10 itens. Pegue o id do último registro na lista e salve para a carga mais funcionalidade. Em seguida, converta a coleção de objects em uma matriz e faça um list.reverse ().

  • CARREGAR MAIS Funcionalidade: A próxima chamada fará duas coisas, obterá a próxima sequência de itens da lista com base no ID de referência da primeira solicitação e fornecerá um indicador se você precisar exibir o botão “carregar mais”.

this.FBRef .child (“childName”) .endAt (null, lastThreadId) // Obtenha isso da etapa anterior .limitToLast (loadMoreLimit + 2)

  • Você precisará remover o primeiro e o último item dessa coleção de objects. O primeiro item é a referência para obter essa lista. O último item é um indicador para o botão show more.

  • Eu tenho um monte de outras lógicas que manterão tudo limpo. Você precisará adicionar este código somente para a carga mais funcionalidade.

      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. } 

Estou usando o ReactFire para facilitar a integração do Firebase.

Basicamente, isso me ajuda a armazenar os dados no estado do componente, como um array . Então, tudo que eu tenho que usar é a function reverse() ( leia mais )

Aqui está como eu consigo isso:

 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 ( 
{ this.state.articles.reverse().map(function(article) { return
{article.title}
}) }
); } }

No Android, há uma maneira de realmente inverter os dados em um Array de objects através do adaptador. No meu caso eu não pude usar o LayoutManager para reverter os resultados em ordem descendente desde que eu estava usando uma Recyclerview horizontal para exibir os dados. Definir os seguintes parâmetros para a exibição de recyclerview desordenou minha experiência de interface do usuário:

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

A única maneira de trabalhar que encontrei em torno disso foi através do método BindViewHolder do adaptador RecyclerView:

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

Espero que essa resposta ajude todos os desenvolvedores que estão lutando com esse problema no Firebase.

Há um caminho melhor. Você deve fazer o pedido pelo registro de data e hora do servidor negativo. Como obter o carimbo de data / hora do servidor negativo mesmo offline? Existe um campo oculto que ajuda. Fragmento relacionado da documentação:

 var offsetRef = new Firebase("https://.firebaseio.com/.info/serverTimeOffset"); offsetRef.on("value", function(snap) { var offset = snap.val(); var estimatedServerTimeMs = new Date().getTime() + offset; }); 

Para adicionar à resposta de Dave Vávra, eu uso um timestamp negativo como meu sort_key como assim

Configuração

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

Obtendo

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

Isso busca todos os objects, do mais novo ao mais antigo. Você também pode $indexOn a sortKey para fazê-lo funcionar ainda mais rápido

Eu também tive esse problema, encontrei uma solução muito simples para isso que não envolvia manipular os dados de qualquer maneira. Se você está rendendo o resultado para o DOM, em uma lista de algum tipo. Você pode usar o flexbox e configurar uma class para reverter os elementos em seu contêiner.

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

Eu fiz isso por preceder.

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

Alguém apontou que existem duas maneiras de fazer isso:

  1. Manipular os dados do lado do cliente
  2. Faça uma consulta que ordenará os dados

A maneira mais fácil que eu encontrei para fazer isso é usar a opção 1, mas através de um LinkedList . Eu apenas acrescento cada um dos objects à frente da pilha. É flexível o suficiente para permitir que a lista seja usada em um ListView ou RecyclerView . Dessa forma, mesmo que eles entrem em ordem, da mais antiga à mais recente, você ainda pode visualizar ou recuperar, da mais recente para a mais antiga.

Você pode adicionar uma coluna chamada orderColumn onde você economiza tempo

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

agora salve a ordem Longa na coluna chamada orderColumn e quando você recuperar dados como orderBy (orderColumn), você obterá o que precisa.

apenas use reverse() no array, suponha que se você está armazenando os valores em um array items[] então faça um this.items.reverse()

  ref.subscribe(snapshots => { this.loading.dismiss(); this.items = []; snapshots.forEach(snapshot => { this.items.push(snapshot); }); **this.items.reverse();** },