add support for sub-graph querying in api
This commit is contained in:
parent
1ff7cd7290
commit
1f311e5ea7
|
@ -21,9 +21,11 @@ defmodule Backend.Api do
|
|||
* have a user count (required to give the instance a size on the graph)
|
||||
* the user count is > the threshold
|
||||
* have x and y coordinates
|
||||
|
||||
If `domain` is passed, then this function only returns nodes that are neighbors of that instance.
|
||||
"""
|
||||
@spec list_nodes() :: [Instance.t()]
|
||||
def list_nodes() do
|
||||
def list_nodes(domain \\ nil) do
|
||||
user_threshold = get_config(:personal_instance_threshold)
|
||||
|
||||
Instance
|
||||
|
@ -32,17 +34,37 @@ defmodule Backend.Api do
|
|||
not is_nil(i.x) and not is_nil(i.y) and not is_nil(i.user_count) and
|
||||
i.user_count >= ^user_threshold
|
||||
)
|
||||
|> maybe_filter_nodes_to_neighborhood(domain)
|
||||
|> select([c], [:domain, :user_count, :x, :y])
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
# if we're getting the sub-graph around a given domain, only return neighbors.
|
||||
defp maybe_filter_nodes_to_neighborhood(query, domain) do
|
||||
case domain do
|
||||
nil ->
|
||||
query
|
||||
|
||||
_ ->
|
||||
query
|
||||
|> join(:inner, [i], outgoing_edges in Edge, on: outgoing_edges.source_domain == i.domain)
|
||||
|> join(:inner, [i], incoming_edges in Edge, on: incoming_edges.target_domain == i.domain)
|
||||
|> where(
|
||||
[i, outgoing_edges, incoming_edges],
|
||||
outgoing_edges.target_domain == ^domain or incoming_edges.source_domain == ^domain
|
||||
)
|
||||
|> distinct(true)
|
||||
end
|
||||
end
|
||||
|
||||
@spec list_edges() :: [Edge.t()]
|
||||
def list_edges() do
|
||||
def list_edges(domain \\ nil) do
|
||||
user_threshold = get_config(:personal_instance_threshold)
|
||||
|
||||
Edge
|
||||
|> join(:inner, [e], i1 in Instance, on: e.source_domain == i1.domain)
|
||||
|> join(:inner, [e], i2 in Instance, on: e.target_domain == i2.domain)
|
||||
|> maybe_filter_edges_to_neighborhood(domain)
|
||||
|> select([e], [:id, :source_domain, :target_domain, :weight])
|
||||
|> where(
|
||||
[e, i1, i2],
|
||||
|
@ -53,6 +75,27 @@ defmodule Backend.Api do
|
|||
|> Repo.all()
|
||||
end
|
||||
|
||||
defp maybe_filter_edges_to_neighborhood(query, domain) do
|
||||
case domain do
|
||||
nil ->
|
||||
query
|
||||
|
||||
_ ->
|
||||
# we want all edges in the neighborhood -- not just edges connected to `domain`
|
||||
query
|
||||
|> join(:inner, [e], neighbor_edges in Edge,
|
||||
on:
|
||||
neighbor_edges.source_domain == e.target_domain or
|
||||
neighbor_edges.target_domain == e.source_domain
|
||||
)
|
||||
|> where(
|
||||
[e, i1, i2, neighbor_edges],
|
||||
e.source_domain == ^domain or e.target_domain == ^domain or
|
||||
neighbor_edges.source_domain == ^domain or neighbor_edges.target_domain == ^domain
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def search_instances(query, cursor_after \\ nil) do
|
||||
ilike_query = "%#{query}%"
|
||||
|
||||
|
|
|
@ -10,4 +10,10 @@ defmodule BackendWeb.GraphController do
|
|||
edges = Api.list_edges()
|
||||
render(conn, "index.json", nodes: nodes, edges: edges)
|
||||
end
|
||||
|
||||
def show(conn, %{"id" => domain}) do
|
||||
nodes = Api.list_nodes(domain)
|
||||
edges = Api.list_edges(domain)
|
||||
render(conn, "index.json", nodes: nodes, edges: edges)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,7 +9,7 @@ defmodule BackendWeb.Router do
|
|||
pipe_through(:api)
|
||||
|
||||
resources("/instances", InstanceController, only: [:index, :show])
|
||||
resources("/graph", GraphController, only: [:index])
|
||||
resources("/graph", GraphController, only: [:index, :show])
|
||||
resources("/search", SearchController, only: [:index])
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue