2011-12-13 22 views
6

estoy poniendo en práctica una API REST que expone órdenes como un recurso y es compatible con la paginación a través del conjunto de resultados:¿Cómo implementar una paginación robusta con una API RESTful cuando el conjunto de resultados puede cambiar?

GET /orders?start=1&end=30 

donde las órdenes de paginar están ordenadas según la ordered_at marca de tiempo, descendiendo. Este es básicamente el enfoque # 1 de la pregunta SO Pagination in a REST web application.

Si el usuario solicita la segunda página de pedidos (GET /orders?start=31&end=60), el servidor simplemente volver a consulta la tabla de órdenes, ordena por ordered_at DESC de nuevo y devuelve los registros en las posiciones 31 a 60.

El problema que tengo es : ¿Qué sucede si el conjunto de resultados cambia (por ejemplo, se agrega una nueva orden) mientras el usuario está viendo los registros? En el caso de que se agregue un nuevo pedido, el usuario vería el anterior # 30 en la primera posición en la segunda página de resultados (porque el mismo pedido ahora es # 31). Peor aún, en el caso de una eliminación, el usuario ve el orden # 32 anterior en la primera posición en la segunda página (# 31) y no vería el antiguo # 31 (ahora # 30) en absoluto.

No puedo ver una solución a esto sin hacer de alguna manera que el servidor RESTful sea estable (urg) o generando cierta inteligencia de paginación en cada cliente ... ¿Cuáles son algunas técnicas establecidas para manejar esto?

Para completar: mi back-end se implementa en Scala/Spray/Squeryl/Postgres; Estoy construyendo dos clientes front-end, uno en backbone.js y el otro en Python Django.

Respuesta

5

La forma en que lo haría, es hacer que los índices se vuelvan viejos a nuevos. Entonces nunca cambian. Y luego, al consultar sin ningún parámetro de inicio, devuelve la página más nueva. Además, la respuesta debe contener un índice que indique qué elementos están contenidos, de modo que pueda calcular los índices que necesita solicitar para la próxima página anterior. Si bien esto no es exactamente lo que quieres, me parece la solución más fácil y limpia.

petición inicial: GET /orders?count=30 devuelve:

{ 
    "start"=1039; 
    "count"=30; 
    ...//data 
} 

A partir de este consumidor calcula que quiere solicitar:

siguientes solicitudes:GET /orders?start=1009&count=30 que luego devuelve:

{ 
    "start"=1009; 
    "count"=30; 
    ...//data 
} 

en lugar de r aw índices también se puede devolver un enlace a la página siguiente:

{ 
    "next"="/orders?start=1009&count=30"; 
} 

Este enfoque se rompe si los artículos se insertan o se eliminan en el medio. En ese caso, debe usar algún valor persistente que aumente automáticamente en lugar de un índice.

1

La triste verdad es que todos los sitios que veo tienen paginación "rota" en ese sentido, por lo que no debe haber una manera fácil de lograr eso.

Una solución rápida podría revertir el orden, por lo que la posición de los elementos es absoluta e invariable con nuevas incorporaciones. Desde su página principal, puede proporcionar los índices más recientes para garantizar una navegación coherente desde allí.

  • Pros: url mismo da los mismos resultados
  • Contras: no hay manera evidente para obtener los últimos elementos ... Tal vez usted podría utilizar índices negativos y redirigir la página de resultados de los índices absolutos.
1

Con una API RESTFULA, el estado de la aplicación debe estar en el cliente. Aquí, el estado de la aplicación debe tener algún tipo de indicación de fecha y hora o número de versión cuando comenzó a buscar los datos. En el lado del servidor, necesitará algún tipo de pista de auditoría, que sea datos del servidor propiamente dichos, ya que no depende de si ha habido clientes y qué han hecho. Por lo menos, debe saber cuándo cambió la información por última vez. No hay contradicción con REST aquí.

Puede agregar un parámetro de versión a su get. Cuando el cliente requiere una página por primera vez, normalmente no envía una versión. El servidor responde contiene uno. Por ejemplo, si hay enlaces en la respuesta a la siguiente/otras páginas, esos enlaces contienen & versión = ... El cliente debe enviar la versión cuando requiera otra página.

Cuando el servidor recibe alguna solicitud con una versión, al menos debe saber si los datos han cambiado desde que el cliente comenzó a buscar y, dependiendo de qué tipo de pista de auditoría tiene, cómo han cambiado. Si no lo han hecho, responde normalmente, transmitiendo el mismo número de versión. Si lo tienen, al menos puede decirle al cliente. Y dependiendo de cuánto sabe sobre cómo han cambiado los datos, puede adaptar la respuesta en consecuencia.

Solo como ejemplo, suponga que obtiene una solicitud con inicio, final, versión, y que sabe que desde que la versión estuvo actualizada, se eliminaron 3 filas antes del inicio. Puede enviar un redireccionamiento con start-3, end-3, nueva versión.

1

WebSockets puede hacer esto. Puede usar algo como pusher.com para detectar cambios en tiempo real en su base de datos y pasar los cambios al cliente. A continuación, puede enlazar diferentes eventos de empuje para trabajar con modelos y colecciones.

0

Just Going to throw it there. Por favor, siéntete libre de decirme si está completamente equivocado y por qué.

Este enfoque intenta utilizar una variable left_off para ordenar sin usar desplazamientos.

Considere que debe hacer su resultado Ordenado por la marca de tiempo order_at DESC. Así que cuando pido primer conjunto de resultados es

SELECT * FROM Orders ORDER BY order_at DESC LIMIT 25; 

¿verdad? Este es el caso cuando se pide la primera página (en términos de URL, probablemente, la solicitud que no tienen ningún

yoursomething.com/orders? límite = 25 = $ & left_off marca de tiempo

. entonces Cuando se recibe el conjunto de datos sólo agarrar la marca de tiempo del último elemento se ve 2015-12-21 13:00:49

Ahora Solicitar a próximos 25 artículos ir a:. yoursomething.com/orders?limit= 25 & left_off = 2015-12-21 13:00:49 (marca de tiempo para, por último, se ve)

en SQL que acaba de hacer la misma consulta y decir donde marca de tiempo es igual o inferior a $ left_off

SELECT * FROM (SELECT * FROM Orders ORDER BY order_at DESC) as a 
WHERE a.order_at < '2015-12-21 13:00:49' LIMIT 25; 

usted debe conseguir una próximos 25 elementos desde el último elemento visto .

Para quienes tengan esta respuesta. Comente si este enfoque es relevante o incluso posible en primer lugar. Gracias.

Cuestiones relacionadas