add support for sub-graph querying in api

This commit is contained in:
Tao Bror Bojlén 2019-07-23 18:04:47 +03:00
parent 1ff7cd7290
commit 1f311e5ea7
No known key found for this signature in database
GPG Key ID: C6EC7AAB905F9E6F
3 changed files with 52 additions and 3 deletions

View File

@ -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}%"

View File

@ -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

View File

@ -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