2017-12-19 3 views
0

Ich verwende Absinth mit Elixier (Phoenix 1.3). Ich habe eine Blog-App, die Benutzer, Posts und Likes enthält, und die Likes werden mit einer Viele-zu-Viele-Beziehung zwischen Benutzern und Posts verknüpft.Hinzufügen von Aggregatfeldern zu Elixir graphql

Sagen wir, ich möchte sie auf dem Back-End eher als die Front aggregieren. Ich möchte :liked_by einfach eine Zählung aller Gleichen sein, die vorhanden sind, eher wie field :likes, :int, so dass ich wieder Antworten wie diese bekommen:

{ 
    "data": { 
    "post" : { 
     "title" : "Title", 
     "content" : "This is the content", 
     "likes" : 7 
    } 
    } 
} 

Was würde mein Objekt muss aussehen? Ich möchte so etwas wie dies zu tun:

object :post do 
    field :id, :integer 
    field :title, :string 
    field :content, :string 
    field :likes, :integer, resolve: assoc(:liking_users, fn query, id, _ -> 
     query |> from like in MyApp.Content.Like, where: like.post_id == ^id, select: count("*") 
    ) 
    end 

EDIT # 1: Genauer gesagt, Ich mag würde wissen, wie eine anonyme Funktion im Absinth-Objekt zu parametrieren. Ich kann das Objekt erhalten eine nicht parametrisierte Wert leicht zurück:

field :somenumber, :integer, resolve: fn (_,_) -> {:ok, 15} end 

Aber das Hinzufügen eines Parameters wie so

field :somenumber, :integer, resolve: fn (foo,_) -> {:ok, foo} end 

gibt Folgendes zurück:

... 
"somenumber": {}, 
... 

Wie kann ich pass in ID des Objekts oder eine implizit zugeordnete Abfrage?

EDIT # 2: Ich habe eine Lösung gefunden, aber es fühlt sich sehr hacky.

object :post do 
    field :id, :integer 
    field :title, :string 
    field :content, :string 
    field :likes, :integer, resolve: fn (_,_,resolution) -> 
     {:ok, Post.getLikeCount(resolution.source.id) } 
    end 
    end 
+1

'Feld: Likes,: Ganzzahl, Auflösung: & Post.get_likes/3' mit einer benutzerdefinierten' Post.get_likes/3' Implementierung sollte tun. Weitere Informationen finden Sie unter "Absinthe.Schema.Notation.resolve" (https://hexdocs.pm/absinthe/Absinthe.Schema.Notation.html#resolve/1). – mudasobwa

+0

@mudasobwa Näher kommen, siehe oben bearbeiten –

+1

Sie müssen nicht assoc verwenden, setzen Sie einfach eine Funktion, die Integer gibt. Außerdem sollte assoc wahrscheinlich auch funktionieren. Hast du einen Fehler oder was? – mudasobwa

Antwort

1

Nach folgendem @ mudasobwa Rat, habe ich diese Lösung:

object :post do 
    field :id, :integer 
    field :title, :string 
    field :content, :string 
    field :likes, :integer, resolve: fn (query,_,_) -> 
     Post.getLikeCount(query.id) 
    end 
    end 

resolution, das dritte Argument der arity 3 anonymen Funktion für den Resolver ist ein Absinthe.Resolution Objekt. resolution.source ist vom Typ MyApp.Content.Post, von denen sich id auf diesen Beitrag bezieht.

Dann habe ich gerade eine Funktion in Post.ex getLikeCount/1 hinzugefügt, die die Anzahl der Likes bekommt.

def getLikeCount (post_id) do 
    query = 
     from l in MyApp.Content.Likes, 
     where: l.post_id == ^post_id, 
     select: count("*") 

    case Repo.one(query) do 
     nil -> {:error, "Error getting like count for post #{post_id}"} 
     likes -> {:ok, likes} 
    end 
    end 
+1

[Repo.one/2'](https://hexdocs.pm/ecto/Ecto.Repo.html#c:one/2) wäre hier wahrscheinlich besser geeignet. Außerdem verstehe ich nicht, warum diese Lösung hacky ist. BTW, laut der Dokumentation, sollte der erste Parameter in einem Aufruf zum Resolver "Post.id" sein, oder? – mudasobwa

+1

Aktualisiert. Es scheint auch, dass die erste Variable in der Funktion arity 3 genau das enthält, wonach ich gesucht habe, so dass es sich nicht mehr hacky anfühlt. –