defmodule Backend.Instance do @moduledoc """ Model for storing everything related to an instance: not only the data from crawls, but also statistics, the time of the next scheduled crawl, X and Y coordinates on the graph, and so on. """ use Ecto.Schema import Ecto.Changeset schema "instances" do field :domain, :string field :description, :string field :user_count, :integer field :status_count, :integer field :version, :string field :insularity, :float field :type, :string field :statuses_per_day, :float field :base_domain, :string field :opt_in, :boolean field :opt_out, :boolean field :next_crawl, :naive_datetime field :crawl_error, :string field :crawl_error_count, :integer many_to_many :peers, Backend.Instance, join_through: Backend.InstancePeer, join_keys: [source_domain: :domain, target_domain: :domain] # This may look like it's duplicating :peers above, but it allows us to insert peer relationships quickly. # https://stackoverflow.com/a/56764241/3697202 has_many :instance_peers, Backend.InstancePeer, foreign_key: :source_domain, references: :domain timestamps() end @doc false def changeset(instance, attrs) do instance |> cast(attrs, [ :domain, :description, :user_count, :status_count, :version, :insularity, :updated_at, :type, :statuses_per_day, :base_domain, :opt_in, :opt_out, :next_crawl, :crawl_error, :crawl_error_count ]) |> validate_required([:domain]) |> put_assoc(:peers, attrs.peers) end defimpl Elasticsearch.Document, for: Backend.Instance do def id(instance), do: instance.id def routing(_), do: false def encode(instance) do # Make sure this corresponds with priv/elasticseach/instances.json %{ domain: instance.domain, description: instance.description, type: instance.type, user_count: instance.user_count, opt_out: instance.opt_out } end end end