Come collegare i filtri di richiesta al modello di dati in un'API REST

2

Sto provando a creare un API di ricerca RESTful (richiesta POST) che può restituire diversi tipi di risorse (ad esempio A, B, C, ecc.). Ho definito un modello di dati per ciascun tipo di risorsa. Ci sono alcune proprietà comuni a tutti i tipi e ce ne sono alcune specifiche per alcuni tipi.

"A" : {
    "a_property1",
    "a_property2",
    "property1",
    "common_property"
}

"B": {
    "b_property1",
    "b_property2",
    "property1",
    "common_property"       
}

"C": {
    "c_property1",
    "common_property"           
}

richiesta di esempio

{
    q : "dog",
    filters: {
        "common_property" : 123, //put the common filters outside 
        "A" : {
            //put all type A specific filters inside
            "A.a_property1" : 100,
            "A.a_property2": "value",
        },
        "B" : {
            //put all type B specific filters here
            "B.b_property1": "value"
        }
    }
}

Sto cercando di legare l'oggetto richiesta allo stesso modello di dati (si sentirebbe simmetrico in quel modo).

Domande:

  1. come rappresentare i filtri per le proprietà che fanno parte di più di un tipo ma non di tutti i tipi. ad esempio "property1"?
  2. è una buona idea legare la richiesta al modello di dati delle risorse?

EDIT:

Prendiamo Google come esempio

/search
{
    "q" : "paris"
    "verticals" : ["web","images","maps","news"] // or ["all"]
    "filter" : {
        "common.last_modified": "2017-01-01"
    }
    "sort" : "relevance"
}


/search
{
    "q" : "paris"
    "verticals" : ["images"] 
    "filter": {
        "image.type" : "Line Drawing",
        "image.color" : "Red"
    }
"sort" : "relevance"
}

Uno dei motivi per cui mi piace il prefisso è che qualifica dove il filtro appartiene. In questo caso questi filtri non hanno alcun senso per la ricerca sul Web, quindi possiamo generare un errore.

/search 
{
    "q" : "paris"
    "verticals" : ["web"] // or ["all"]
    "filter": {
        "image.type" : "Line Drawing",
        "image.color" : "Red",
        "web.category": "travel"
    }
    "sort" : "relevance"
}

NOTA: Ho modificato leggermente la richiesta per rimuovere le sezioni come A, B, C nella richiesta poiché sembrava complicata.

    
posta srini 05.08.2016 - 17:25
fonte

3 risposte

0

Oltre a

is it a good idea to tie the request to the data model of the resources?

Direi no .

Perché?

Hai esposto un modello di dati molto piatto. Ma cosa faresti con modelli come:

"D" : { 
     "a_property1", 
     "a_property2", 
     "property1", 
     "common_property" ,
     "complex_property":{
          "more_complexity":{...}
       }
     }

Stai accoppiando strettamente un modello a molti altri, di conseguenza, ogni nuova entità che arriva lungo il sistema ti costringe a rifattorizzare il modello di dati della query.

Questo approccio non scalerà bene e la sua manutenzione sarà costosa alla fine.

Un buon approccio è guardare la ricerca come una risorsa. Verifica questa domanda

Modello dati query

Diciamo che trasformiamo il tuo esempio in qualcosa di meno accoppiato.

{ 
         "entity":"dog",
         "filters":{
               "name":"value",
               "name":"value",
               "name.attr.attr":"value"
           }
  }

E lascia che lo chiami QueryDTO .

Una volta sul server, dobbiamo trasformare la query in filtri applicabili a tutte le possibili entità del modello dati.

public interface QueryTransformer<T>{
      T transform(QueryDTO query);
}

"T" è una qualsiasi delle entità del modello di dati. Trasformatore mappe filtri agli attributi T . Quelli che non corrispondono vengono ignorati.

Transformer genera un esempio di T , che può essere usato (come modello) per generare i criteri per filtrare tale entità.

L'idea è di dividere un grosso problema (modello dati di query) in molti ma più piccoli (trasformatori).

L'approccio riduce la complessità. Rende astratta la mappatura e utilizza il modello di dati esistente. Inoltre si adatta meglio del primo scopo. La manutenzione è anche più economica.

QueryDTO può essere complesso quanto necessario, ma più è complesso, più è difficile implementare questi trasformatori. Ma ancora scalabile ed economico.

    
risposta data 07.10.2016 - 22:12
fonte
1

Sembra strano usare un POST (usato per creare dati sul server che può essere quello che vuoi) per quella che è davvero una richiesta GET (recupero dei dati). I filtri possono essere inseriti nella stringa di query per scopi di memorizzazione nella cache, se necessario, e per facilitare il debug. Ad esempio.

GET /api/resources?q=dog&filter_common_property=123&filter_property1=value@filter_a_property1=100

È possibile analizzare filtri di oggetti specifici dalla chiave, ad esempio filter_property1 = il valore è globale e filter_a_property1 è locale all'oggetto A.

Da una prospettiva REST sembrerebbe anche più sensato interrogare ogni risorsa singolarmente GET /api/A?.... a meno che non ci siano requisiti prestazionali di cui non sono a conoscenza.

    
risposta data 05.01.2017 - 22:58
fonte
0

Un approccio sarebbe ripetere la proprietà per ogni tipo che stai interrogando. In altre parole, non hai l'opzione per un filtro "globale".

    
risposta data 08.08.2016 - 10:37
fonte

Leggi altre domande sui tag