2015-10-16 15 views
5

In Ecto si possono fare interrogazioni riutilizzabili/componibili in questo modo:Elixir Ecto: più join e/query componibili riutilizzabili

defmodule AModel 
    #... 

    def anonymous(q), do: q |> where([am], is_null(am.user_id)) 
end 

Vedi altri esempi on this blog post.

Tuttavia, devo affrontare un problema utilizzando più join.

Supponiamo di avere uno schema che assomiglia a questo:

  • Amodel appartiene alla BModel
  • BModel appartiene alla CModel
  • CModel appartiene alla DModel

La soluzione proposta in questo l'articolo non funziona davvero con i join profondi:

q = DModel 
|> join(:inner, [dm], cm in assoc(dm, :c_models)) 
|> join(:inner, [_, cm], bm in assoc(cm, :b_models)) 
|> join(:inner, [_, _, bm], am in assoc(bm, :a_models)) 
|> AModel.anonymous 

Le funzioni di query prendono come primo argomento (secondo per join) una tabella di associazione. Contiene i precedenti join ed è purtroppo stretto per unire l'ordine.

Nel nostro caso, la funzione anonymous ha come destinazione la tabella di partenza. Tuttavia, nell'esempio di query, AModel è il 4o legame ...

Qualche idea o tecnica per sbarazzarsi di questa dipendenza dall'ordine?

EDIT:

ricevo una risposta dal blog dell'autore. Mi ha detto che non esiste un altro modo nativo per gestire i binding rispetto alla posizione nella tabella. Ha anche dato this article evidenziando questo fatto.

Ma per amor di dio, se l'ordine conta solo, perché non riesco a creare sopra di esso una mappatura dei nomi che associa il nome all'indice vincolante?

È troppo chiedere: p?

+1

Uno dei creatori di Ecto qui. Questo è in realtà un problema molto difficile da risolvere perché, finché leghiamo i nomi, la possibilità di conflitti aumenta notevolmente, specialmente perché amiamo usare scorciatoie, come hai usato am, bm e così via. Ma sappiamo che l'affare attuale è anche un fastidio, ma non abbiamo ancora una buona soluzione (ancora). –

+0

Stavo pensando di provare a creare una sovrapposizione sopra l'elenco di rilegature. Quando si effettua il join, posso dare un nome di simbolo che corrisponde alla posizione di rilegatura. Quindi, usando 'where', posso estrarre l'associazione richiesta fornendo il nome. Pensi che sia attualmente possibile creare tale meccanismo? Stavo pensando di usare la funzione di tipo monad che restituirebbe {query, binding_names} ... – ProxyGear

+1

Non credo che sarete in grado di ottenerlo senza modificare Ecto.Puoi dare la posizione, credo, come in 'def anonymous (q, pos), do: q |> dove ([am: pos], is_null (am.user_id))' ma questo è peggio IMO. –

risposta

-1

Forse creare qualche junction tables?


EDIT: Vedo che forse ero un po 'troppo conciso. Voglio dire che puoi costruire tabelle di giunzione sul back-end e poi interrogarle. In questo modo non devi preoccuparti di costruire i join nel tuo codice Ecto. Spero di rendere la mia risposta un po 'più chiara.

+0

Non vedo come le giunzioni possono aiutare qui. Puoi fornire maggiori dettagli? – ProxyGear

+0

Ho modificato la mia risposta per dare un po 'più di dettaglio. –

+0

Ok, grazie per la modifica. Tuttavia questo significa: a) duplicare/alterare lo schema dei dati per risolvere un problema programmatico, suona male. b) Può davvero permetterselo a causa della dimensione dei dati – ProxyGear