2010-08-18 16 views
6

tengo API REST realizarán siguiendo el principio de que el resto sólo devuelve los documentos básicos y las referencias en esos documentos COMO conseguir otras cosas, etc, etcAPI REST de clasificación dilema

Por ejemplo, un/coche/5 me dará modelo: blabla, user_id: 1 y luego si necesita el propietario obtendrá/user/1 para obtener datos de usuario ...

De esta manera se une y se evitan cosas en DB ... todas las cosas están vinculadas entre sí y los datos están interconectados en la parte del cliente de reposo - simplificando las cosas fácil de caché/soltar el caché, escalar, etc.

Pero, ¿qué sucede cuando necesita ordenar?

Imaginemos que tenemos alguna vista en la interfaz para mostrar los siguientes datos: Modelo de coche, nombre de usuario, etc. ... y que desea ordenar por nombre de usuario, por ejemplo.

realmente no se puede decir la/coche/5 para ordenar por nombre de usuario causa que sólo sabe de identificadores de usuario ...

Una opción que veo es la clasificación de usuario/usuario/listado? SortBy = nombre de usuario y luego interconectando cuál de esos ID devueltos realmente se refiere al automóvil. pero esto significa que tenemos que obtener TODOS los usuarios ... y solo usar una fracción de los que parece un cuello de botella de rendimiento desastroso.

Gracias por cualquier punteros

Respuesta

5

Creo que está tratando de evitar unirse por todas las razones equivocadas, como mediante la adopción de este enfoque, que van a tener que dar servicio a una gran cantidad más solicitudes.

Si en lugar de traer de vuelta a toda la información que desea mostrar (es decir, hacer las uniones lado de la base de datos), a continuación, los clientes van a tener que hacer menos preguntas, y usted podría hacer su clase sin tener que (perezoso) cargar todos los objetos secundarios.

La otra opción sería volver a traer los objetos secundarios como elementos XML secundarios (de forma similar a cómo funciona la interfaz RESTful de OpenStreetMap). Aún tiene un solo golpe del cliente, y debería poder optimizar las consultas para minimizar la carga en el DB.

4

Si está evitando todas las uniones en el servidor y dejándolo al cliente, en este caso debe dejar la clasificación también al cliente. Esto se debe a que debe tener lugar una unión para ordenar los autos por nombre de usuario.

Puede crear otro recurso llamado CarsAndOwners o similar que devuelva la lista unida, en cuyo punto es razonable ordenar en el servidor.

2

me gustaría empezar por imaginar la consulta REST ideal que me gustaría escribir, por ejemplo:

/car/list?sortby=username 

Y luego encontrar la manera de poner en práctica eso.

Ahora su lista método le da coche objetos que no exponga nombre de usuario como usted ha dicho, pero no creo que lo que importa. Toda la clasificación debe tener lugar en el servidor antes de que la lista esté preparada.

usted va a necesitar para unirse a su coche objetos de usuario objetos en algún momento con el fin de hacer esto, y no hay manera de esquivar la cuestión. La única opción que tienes es dónde lo haces.

Si está trabajando con un RDBMS tradicional, tiene sentido hacerlo en el nivel DB.


¿Está utilizando una capa ORM entre la API de la aplicación y la base de datos?

+0

bien, toda la persistencia está detrás del REST ... actualmente el resto está usando ORM, pero no creo que esto sea relevante. –

+1

Me dieron la pista de que estaba utilizando ORM porque dijo que estaba evitando uniones en el DB y conectando todos sus objetos en la capa de la aplicación REST. Puedo ver el atractivo de esta arquitectura simple y limpia, pero es probable que esté en la raíz de su dilema actual. Intentaré poner en peligro esta arquitectura para que la aplicación funcione: tener procs o vistas almacenados adicionales en el DB que devuelven los datos pre-ordenados, aún proporcionando mapeo ORM para estos objetos, y dejando que la aplicación REST escoja entre métodos dependiendo de la consulta. –

2

En primer lugar, tu ejemplo /car/5 debe ser la versión plural de los recursos con el fin de ser REST:

/cars/5 
/users/1 

Ahora, en general, si quieres un enfoque REST a la clasificación se puede hacer esto:

/cars?sort=make&order=asc 

En su ejemplo, usted menciona que desea ordenar los autos por nombre de usuario. Sin embargo, como mencionas, la colección cars no debe saber nada sobre users. Entonces, si desea mostrar una lista de automóviles y agruparlos por usuario, ¿qué hace? Necesitas una forma de recuperar esta información. Una forma de hacer esto es colocar a través de los usuarios y solicitar los coches asociados a cada usuario:

# pseudo code 

users.each do |user| 
    # assuming the user id is 5, 
    # to display the user's cars, 
    # we need to request /users/5/cars 
end 

Por lo tanto, puede solicitar la lista de coches para cada individuo en una URL como /users/5/cars. Esto se conoce como un recurso anidado. Solo estamos solicitando los automóviles que están relacionados con el usuario 5.

Sin embargo, entonces tiene el problema de potencialmente hacer muchas solicitudes a su API (lo que puede estar bien dependiendo de su caso de uso).

Otro enfoque, que es probablemente mejor, es hacerlo de una solicitud a:

/users/cars?sort=username&order=asc 

Esto devolver una matriz de los usuarios y sus coches solicitados por nombre de usuario.

Y otro enfoque podría ser:

/users?include=[cars]&sort=username&order=asc 

pero no me gusta este enfoque tanto como el anterior. Recomendaría el enfoque anterior de /users/cars.

Nota al margen: las listas debe ser paginado de manera que no es la sobrecarga de solicitar toda del users cuando sólo se está visualizando una lista parcial.

/users?page=1&per_page=50 
+1

La denominación de recursos plural no es un requisito de REST; lo que se requiere es una semántica uniforme para las posibilidades de cada recurso; es decir, cada recurso expuesto debe comportarse del mismo modo (desde la perspectiva del consumidor) a los métodos de protocolo disponibles (GET, POST , DELETE, etc ...) –

1

Las bases de datos están diseñadas para hacer uniones rápidamente, por lo que dejarlo en manos del cliente o de su aplicación de servidor no tiene sentido para mí.

Casi todo lo que he leído en REST dice que las relaciones entre entidades/recursos también deberían ser un recurso. Por lo tanto, debe tener un recurso /mydomain.com/CarsAndUsers que represente esa unión/relación.

entonces usted puede hacer la clasificación en ese recurso como cualquier otro, y que estará a cargo de la base de datos:

/mydomain.com/CarsAndUsers?sortby=username

También puede aplicar el filtro a ese recurso (y paginación) como cualquier otro recurso.

EDIT:

De acuerdo con los comentarios que sería mejor hacer algo como esto:?

/coches incrustar = usuario, SortBy = nombre de usuario

Gracias a Eric por señalar esto afuera.

+0

Esa es una receta para la explosión combinatoria de puntos finales API. Un enfoque REST más común es usar parámetros para solicitar objetos en línea (esencialmente representaciones unidas). Por ejemplo: '/ albums? Embed = artist'. Esos recursos disponibles para la inserción pueden tener enlaces en una colección de hipermedia 'links' para hacer que la opción sea reconocible. –

+0

Gracias Eric, aunque estoy de acuerdo con su punto acerca de la explosión de puntos finales, la pregunta no es sobre objetos relacionados sino sobre ordenar un conjunto basado en la propiedad de un conjunto relacionado. No estoy seguro de lo que estás sugiriendo resuelve ese problema en particular. ¿O está diciendo que el OP podría hacer esto: /cars? Embed = user, sortby = username – rmcsharry

+0

Sí, eso es más o menos lo que estoy sugiriendo. –