Olá, meu nome é Dmitry Karlovsky e tenho novidades para você. Bem, como novidade, uma nova olhada na coisa usual na forma de outro artigo. Provavelmente, você poderá acessá-lo a partir de qualquer feed de notícias. Ou você não entenderá se as notícias forem publicadas na hora errada. Não importa o quão interessante este artigo seja para você.

O problema é como as fitas são formadas e como o usuário interage com elas. E aqui, infelizmente, como sempre, a solução mais simples está extremamente errada. Vamos ver o porquê.
Métodos de consumo
Suponha que um usuário nos solicite uma lista de algumas entidades. Como o usuário visualiza essas entidades depende de seus objetivos. Existem duas maneiras de consumir:
Pesquisa ativa. O usuário está procurando algo específico. Ele aplica filtragem e classificação para restringir a saída, após o que ele varre os materiais sequencialmente, verificando cada um deles. É importante que a lista que você está visualizando não seja alterada durante o processo de visualização; caso contrário, você pode pular facilmente o que está procurando.
Pesquisa passiva. O usuário não está procurando nada específico. Pelo contrário, ele deseja que o serviço verifique o que esse serviço possui e mostre ao usuário algo que será interessante para ele. Aqui é apenas importante mostrar ao usuário os materiais mais relevantes no momento para um usuário em particular. E o que ele já viu não é para mostrar.
Portanto, os feeds de notícias são projetados apenas para o consumo passivo dessas mesmas notícias. Sim, o usuário pode limitar o leque de interesses com a ajuda de filtros, mas ele não está procurando nenhuma notícia específica, pois provavelmente ainda não o conhece e foi ao feed para saber mais. E sua satisfação depende de quanto mais materiais interessantes (relevantes) ele vê e quantos desinteressantes ele vê.
Critérios de relevância
Muitos fatores podem influenciar a relevância. Por exemplo, alterar a prioridade de uma tarefa atribuída a você no gerenciador de tarefas é uma notícia muito importante, que deve ser mostrada ao usuário o mais rápido possível. Mesmo depois disso, houve comentários de uma dúzia de outras tarefas.
Mas existem critérios gerais, como:
- Visibilidade. Se o usuário já viu esta notícia e de alguma forma reagiu a ela (enganado, excluído, marcado como lido, foi aos detalhes etc.), na segunda vez que ele não deseja vê-la.
- Relevância. Algumas notícias perdem sua relevância com o advento de notícias mais recentes sobre o mesmo tópico. Por exemplo, nas notícias sobre a mudança no status da tarefa, apenas a mais recente é interessante, refletindo o estado atual.
- Data Notícias recentes são frequentemente mais interessantes. E algumas notícias antigas não são mais tão interessantes que é melhor não mostrá-las (por exemplo, as notícias de que a água quente foi desligada um dia atrás).
Fitas na vida selvagem
Na grande maioria dos casos, os feeds de notícias são formados pela emissão de materiais classificados pela data de sua criação, publicação ou alteração. Ou seja, os critérios de relevância restantes (mais importantes) simplesmente não são levados em consideração. Em última análise, isso leva à insatisfação do usuário. Alguns exemplos para ilustrar:
Feed do VKontakte
O usuário abre as notícias pela primeira vez e as exibe sequencialmente - tudo está bem aqui. Depois de algum tempo, aparece uma notificação de que algumas notícias recentes apareceram. E então ele tem uma escolha complicada:
- Continue folheando o feed
- Rebobine o feed do início para ver as últimas notícias (o que não é mais relevante).
Como a fita é quase infinita, e a guia do navegador não pode viver para sempre, e ninguém cancelou a curiosidade. Mais cedo ou mais tarde, o usuário estará novamente no "início" da fita. Ok, role para baixo. Nada indica problemas, quando de repente as notícias que o usuário já viu começam a aparecer. E aqui novamente, o usuário não é uma escolha complicada:
- Rápida e rapidamente, enrole a fita, diminuindo o tráfego da Internet, esperando terminar as notícias que ele ainda não tinha visto.
- Dirija na fita e faça outra coisa.
Acontece que toda vez que o usuário não recebe nenhuma notícia, ele nunca a vê. Mas eles poderiam ser interessantes para ele. Além disso, eles podem ser críticos e mudar radicalmente sua vida.
Esse problema é tão típico que é correto atribuir um nome especial a ele. Que seja a "Síndrome da Consciência Fragmentada".
Home Habra
A OFS aqui é agravada pela paginação. Ao alternar entre as páginas, o usuário vê as notícias da página anterior. E se ele permanecer em algumas páginas um pouco mais, poderá facilmente obter algumas páginas de “abate” seguidas. Descrevi esse problema com mais detalhes em uma nota sobre Pajinization .
Youtube
No "recomendado", basta dar 18 vídeos assustadores e é isso. Para ver algo novo nas recomendações, você precisa excluir manualmente tudo o que não causou interesse. Obviamente, um usuário raro fará isso. Nas "assinaturas" - eles simplesmente classificam por data, por causa da qual os clipes antigos, mas possivelmente interessantes para o usuário, ele nunca verão. A menos que tropeça neles no "recomendado".
Raiz do problema
Quando o usuário abriu o feed pela primeira vez, ele tinha apenas um ponto de recebimento de notícias - imediatamente após a visualização anterior. Ele olha para eles e de repente um segundo ponto de entrada aparece - em algum lugar acima. E é difícil dizer onde as notícias são mais relevantes. Quando, depois de um intervalo, ele retorna, ele imediatamente tem pelo menos dois pontos: o início da fita e o local em que ele terminou de assistir as notícias da última vez. E como o usuário não tem a oportunidade de assistir às notícias antes de visualizadas anteriormente, esses pontos de recebimento de notícias estão se multiplicando e se multiplicando.
Solução
O ponto de recebimento de notícias relevantes deve ser apenas um. Ao mesmo tempo, as notícias mais relevantes em tempo real devem ser recebidas. Entre todas as notícias, podemos destacar os seguintes grupos:
- Visível. As notícias que recebemos anteriormente para ele e ele vê agora na tela.
- Visualizados. Notícias que o usuário já assistiu e rolou. Quando a notícia deixa a área visível para cima - você pode marcá-la com segurança como lida.
- A história Uma lista de notícias gerada para um usuário específico. Isso inclui as notícias que o usuário já visualizou e as que ele está vendo no momento.

Idealmente, mesmo recarregar a página não deve mudar nada na lista de notícias. Quando o usuário solicita mais notícias (clicando no botão ou rolando para baixo), selecionamos outra parte das notícias mais relevantes no momento e as colocamos na história. Assim, o usuário tem uma ideia clara da fita como algo interessante e não muda. Tudo o que ele já viu está na ordem em que ele viu. E, abalando, ele constantemente obtém algo interessante, sem se preocupar com o fato de que algo vai faltar. É verdade que pode ser necessário dar corda por muito tempo, se houver muitas notícias.
Relevância
A coisa mais simples, é claro, é simplesmente considerar as últimas notícias mais relevantes. Mas você pode permitir que o usuário ajude o serviço a entender o que lhe interessa e o que não interessa. Você pode fazer isso adicionando a capacidade de excluir notícias. Se o usuário não apenas rolou as notícias, mas a excluiu para não obstruir sua história, esse tipo de notícia não é interessante para ele e essas informações podem ser usadas para compilação subsequente.
API
Como nossa história está sendo reabastecida e visualizada a partir do final, não podemos usar a paginação tradicional, porque as notícias passam constantemente entre as páginas. Além disso, solicitar cerca de 100500 páginas para o DBMS pode ser muito pesado. Portanto, para amostragem de dados, usaremos âncoras. Para isso, indicaremos os seguintes dados na solicitação:
- Âncora O identificador das notícias a partir das quais os dados devem ser retornados. Se a âncora não for especificada, as últimas notícias lidas serão consideradas como âncora.
- Deslocamento. O número de notícias a serem amostradas. Esse número pode ser positivo e as notícias retornam após a âncora. Ou negativo e, em seguida, as notícias retornam à âncora.
Se o viés for negativo, mas não houver um número necessário de notícias antes da âncora, simplesmente retornará quanto é. Pela diferença no número de solicitações e no número de visitantes, o cliente pode entender que estamos no início da história.
Se o viés for positivo e não houver um número necessário de notícias após a âncora, a história será complementada no número necessário com as notícias mais relevantes no momento. Se as notícias terminarem completamente, retornamos quanto e o cliente detecta o final da fita.
Script de consulta
Abrimos a fita, ainda não temos âncora:
GET /feed?offset=5
Solicitamos notícias não lidas:
SELECT FROM history WHERE user = 123 AND read_at NOT NULL ORDER BY id ASC limit 5
O usuário vê uma seleção de notícias não lidas nas quais parou da última vez:
[ { id : 3232 } , { id : 5343 } , { id : 7346 } , { id : 9825 } , { id : 9967 } ]
O usuário sobe para ver as notícias que viu da última vez:
GET /feed?anchor=3232&offset=-5
SELECT FROM history WHERE user = 123 AND id < 3232 ORDER BY id DESC limit 5
[ { id : 323 } , { id : 329 } , { id : 544 } , { id : 843 } , { id : 898 } ]
O usuário sacode para ver algo novo:
GET /feed?anchor=7346&offset=5
SELECT FROM history WHERE user = 123 AND id > 7346 ORDER BY id ASC limit 5
Se você receber algumas novidades, selecionamos o número necessário dos mais relevantes ausentes no histórico e os adicionamos ao histórico, após o qual retornamos tudo juntos:
[ { id : 38574} , { id : 47246} , { id : 52378} , { id : 69238} , { id : 73294} ]
Realizações na vida selvagem
Se você conhece algum serviço que implementa feeds dessa maneira ou de maneira semelhante, ficarei feliz em postar links para eles aqui, para que os leitores possam apreciar a conveniência dessa abordagem.