break compile time dependencies for elasticsearch index usage

This commit is contained in:
byte[] 2019-12-24 16:14:42 -05:00
parent 18798d2e99
commit 620f316db8
41 changed files with 374 additions and 234 deletions

View file

@ -1,6 +1,7 @@
defmodule Mix.Tasks.ReindexAll do defmodule Mix.Tasks.ReindexAll do
use Mix.Task use Mix.Task
alias Philomena.Elasticsearch
alias Philomena.{Comments.Comment, Galleries.Gallery, Posts.Post, Images.Image, Reports.Report, Tags.Tag} alias Philomena.{Comments.Comment, Galleries.Gallery, Posts.Post, Images.Image, Reports.Report, Tags.Tag}
alias Philomena.{Comments, Galleries, Posts, Images, Tags} alias Philomena.{Comments, Galleries, Posts, Images, Tags}
alias Philomena.Polymorphic alias Philomena.Polymorphic
@ -16,21 +17,21 @@ defmodule Mix.Tasks.ReindexAll do
{:ok, _apps} = Application.ensure_all_started(:philomena) {:ok, _apps} = Application.ensure_all_started(:philomena)
for {context, schema} <- [{Images, Image}, {Comments, Comment}, {Galleries, Gallery}, {Tags, Tag}, {Posts, Post}] do for {context, schema} <- [{Images, Image}, {Comments, Comment}, {Galleries, Gallery}, {Tags, Tag}, {Posts, Post}] do
schema.delete_index! Elasticsearch.delete_index!(schema)
schema.create_index! Elasticsearch.create_index!(schema)
schema.reindex(schema |> preload(^context.indexing_preloads())) Elasticsearch.reindex(preload(schema, ^context.indexing_preloads()), schema)
end end
# Reports are a bit special # Reports are a bit special
Report.delete_index! Elasticsearch.delete_index!(Report)
Report.create_index! Elasticsearch.create_index!(Report)
Report Report
|> preload([:user, :admin]) |> preload([:user, :admin])
|> Repo.all() |> Repo.all()
|> Polymorphic.load_polymorphic(reportable: [reportable_id: :reportable_type]) |> Polymorphic.load_polymorphic(reportable: [reportable_id: :reportable_type])
|> Enum.map(&Report.index_document/1) |> Enum.map(&Elasticsearch.index_document(&1, Report))
end end
end end

55
lib/philomena/batch.ex Normal file
View file

@ -0,0 +1,55 @@
defmodule Philomena.Batch do
alias Philomena.Repo
import Ecto.Query
@doc """
Load records from the given queryable in batches, to avoid locking.
Valid options:
* :batch_size
* :id_field
"""
def record_batches(queryable, opts \\ [], callback) do
query_batches(queryable, opts, &callback.(Repo.all(&1)))
end
@doc """
Load queries from the given queryable in batches, to avoid locking.
Valid options:
* :batch_size
* :id_field
"""
def query_batches(queryable, opts \\ [], callback) do
ids = load_ids(queryable, -1, opts)
query_batches(queryable, opts, callback, ids)
end
defp query_batches(_queryable, _opts, _callback, []), do: []
defp query_batches(queryable, opts, callback, ids) do
id_field = Keyword.get(opts, :id_field, :id)
queryable
|> where([m], field(m, ^id_field) in ^ids)
|> callback.()
ids = load_ids(queryable, Enum.max(ids), opts)
query_batches(queryable, opts, callback, ids)
end
defp load_ids(queryable, max_id, opts) do
id_field = Keyword.get(opts, :id_field, :id)
batch_size = Keyword.get(opts, :batch_size, 1000)
queryable
|> exclude(:preload)
|> exclude(:order_by)
|> order_by(asc: ^id_field)
|> where([m], field(m, ^id_field) > ^max_id)
|> select([m], field(m, ^id_field))
|> limit(^batch_size)
|> Repo.all()
end
end

View file

@ -7,6 +7,7 @@ defmodule Philomena.Comments do
alias Ecto.Multi alias Ecto.Multi
alias Philomena.Repo alias Philomena.Repo
alias Philomena.Elasticsearch
alias Philomena.Reports.Report alias Philomena.Reports.Report
alias Philomena.Comments.Comment alias Philomena.Comments.Comment
alias Philomena.Images.Image alias Philomena.Images.Image
@ -194,7 +195,7 @@ defmodule Philomena.Comments do
|> preload(^indexing_preloads()) |> preload(^indexing_preloads())
|> where(id: ^comment.id) |> where(id: ^comment.id)
|> Repo.one() |> Repo.one()
|> Comment.index_document() |> Elasticsearch.index_document(Comment)
end end
comment comment
@ -205,7 +206,7 @@ defmodule Philomena.Comments do
Comment Comment
|> preload(^indexing_preloads()) |> preload(^indexing_preloads())
|> where(image_id: ^image.id) |> where(image_id: ^image.id)
|> Comment.reindex() |> Elasticsearch.reindex(Comment)
end end
image image

View file

@ -2,11 +2,6 @@ defmodule Philomena.Comments.Comment do
use Ecto.Schema use Ecto.Schema
import Ecto.Changeset import Ecto.Changeset
use Philomena.Elasticsearch,
definition: Philomena.Comments.Elasticsearch,
index_name: "comments",
doc_type: "comment"
alias Philomena.Images.Image alias Philomena.Images.Image
alias Philomena.Users.User alias Philomena.Users.User

View file

@ -1,4 +1,17 @@
defmodule Philomena.Comments.Elasticsearch do defmodule Philomena.Comments.ElasticsearchIndex do
@behaviour Philomena.ElasticsearchIndex
@impl true
def index_name do
"comments"
end
@impl true
def doc_type do
"comment"
end
@impl true
def mapping do def mapping do
%{ %{
settings: %{ settings: %{
@ -29,6 +42,7 @@ defmodule Philomena.Comments.Elasticsearch do
} }
end end
@impl true
def as_json(comment) do def as_json(comment) do
%{ %{
id: comment.id, id: comment.id,

View file

@ -1,141 +1,142 @@
defmodule Philomena.Elasticsearch do defmodule Philomena.Elasticsearch do
defmacro __using__(opts) do alias Philomena.Batch
definition = Keyword.fetch!(opts, :definition) alias Philomena.Repo
index_name = Keyword.fetch!(opts, :index_name) require Logger
doc_type = Keyword.fetch!(opts, :doc_type) import Ecto.Query
elastic_url = Application.get_env(:philomena, :elasticsearch_url) alias Philomena.Comments.Comment
alias Philomena.Galleries.Gallery
alias Philomena.Images.Image
alias Philomena.Posts.Post
alias Philomena.Reports.Report
alias Philomena.Tags.Tag
quote do alias Philomena.Comments.ElasticsearchIndex, as: CommentIndex
alias Philomena.Repo alias Philomena.Galleries.ElasticsearchIndex, as: GalleryIndex
import Ecto.Query, warn: false alias Philomena.Images.ElasticsearchIndex, as: ImageIndex
require Logger alias Philomena.Posts.ElasticsearchIndex, as: PostIndex
alias Philomena.Reports.ElasticsearchIndex, as: ReportIndex
alias Philomena.Tags.ElasticsearchIndex, as: TagIndex
def create_index! do defp index_for(Comment), do: CommentIndex
Elastix.Index.create( defp index_for(Gallery), do: GalleryIndex
unquote(elastic_url), defp index_for(Image), do: ImageIndex
unquote(index_name), defp index_for(Post), do: PostIndex
unquote(definition).mapping() defp index_for(Report), do: ReportIndex
) defp index_for(Tag), do: TagIndex
end
def delete_index! do defp elastic_url do
Elastix.Index.delete(unquote(elastic_url), unquote(index_name)) Application.get_env(:philomena, :elasticsearch_url)
end end
def index_document(doc) do def create_index!(module) do
data = unquote(definition).as_json(doc) index = index_for(module)
Elastix.Document.index( Elastix.Index.create(
unquote(elastic_url), elastic_url(),
unquote(index_name), index.index_name(),
[unquote(doc_type)], index.mapping()
data.id, )
data end
)
end
def delete_document(id) do def delete_index!(module) do
Elastix.Document.delete( index = index_for(module)
unquote(elastic_url),
unquote(index_name),
unquote(doc_type),
id
)
end
def reindex(ecto_query, batch_size \\ 1000) do Elastix.Index.delete(elastic_url(), index.index_name())
ids = end
ecto_query
|> exclude(:preload)
|> exclude(:order_by)
|> order_by(asc: :id)
|> select([m], m.id)
|> limit(^batch_size)
|> Repo.all()
reindex(ecto_query, batch_size, ids) def index_document(doc, module) do
end index = index_for(module)
data = index.as_json(doc)
def reindex(ecto_query, batch_size, []), do: nil Elastix.Document.index(
elastic_url(),
index.index_name(),
[index.doc_type()],
data.id,
data
)
end
def reindex(ecto_query, batch_size, ids) do def delete_document(id, module) do
lines = index = index_for(module)
ecto_query
|> where([m], m.id in ^ids)
|> Repo.all()
|> Enum.flat_map(fn m ->
doc = unquote(definition).as_json(m)
[ Elastix.Document.delete(
%{index: %{_index: unquote(index_name), _type: unquote(doc_type), _id: doc.id}}, elastic_url(),
doc index.index_name(),
] index.doc_type(),
end) id
)
end
Elastix.Bulk.post(unquote(elastic_url), lines, def reindex(queryable, module, opts \\ []) do
index: unquote(index_name), index = index_for(module)
httpoison_options: [timeout: 30_000]
)
ids = Batch.record_batches(queryable, opts, fn records ->
ecto_query lines =
|> exclude(:preload) Enum.flat_map(records, fn record ->
|> exclude(:order_by) doc = index.as_json(record)
|> order_by(asc: :id)
|> where([m], m.id > ^Enum.max(ids))
|> select([m], m.id)
|> limit(^batch_size)
|> Repo.all()
reindex(ecto_query, batch_size, ids) [
end %{index: %{_index: index.index_name(), _type: index.doc_type(), _id: doc.id}},
doc
]
end)
def search(query_body) do Elastix.Bulk.post(
{:ok, %{body: results, status_code: 200}} = elastic_url(),
Elastix.Search.search( lines,
unquote(elastic_url), index: index.index_name(),
unquote(index_name), httpoison_options: [timeout: 30_000]
[unquote(doc_type)], )
query_body end)
) end
results def search(module, query_body) do
end index = index_for(module)
def search_results(elastic_query, pagination_params \\ %{}) do {:ok, %{body: results, status_code: 200}} =
page_number = pagination_params[:page_number] || 1 Elastix.Search.search(
page_size = pagination_params[:page_size] || 25 elastic_url(),
elastic_query = Map.merge(elastic_query, %{from: (page_number - 1) * page_size, size: page_size, _source: false}) index.index_name(),
[index.doc_type()],
query_body
)
results = search(elastic_query) results
time = results["took"] end
count = results["hits"]["total"]
entries = results["hits"]["hits"] |> Enum.map(&String.to_integer(&1["_id"]))
Logger.debug("[Elasticsearch] Query took #{time}ms") def search_results(module, elastic_query, pagination_params \\ %{}) do
page_number = pagination_params[:page_number] || 1
page_size = pagination_params[:page_size] || 25
elastic_query = Map.merge(elastic_query, %{from: (page_number - 1) * page_size, size: page_size, _source: false})
%Scrivener.Page{ results = search(module, elastic_query)
entries: entries, time = results["took"]
page_number: page_number, count = results["hits"]["total"]
page_size: page_size, entries = Enum.map(results["hits"]["hits"], &String.to_integer(&1["_id"]))
total_entries: count,
total_pages: div(count + page_size - 1, page_size)
}
end
def search_records(elastic_query, pagination_params \\ %{}, ecto_query \\ __MODULE__) do Logger.debug("[Elasticsearch] Query took #{time}ms")
page = search_results(elastic_query, pagination_params)
ids = page.entries
records = %Scrivener.Page{
ecto_query entries: entries,
|> where([m], m.id in ^ids) page_number: page_number,
|> Repo.all() page_size: page_size,
|> Enum.sort_by(&Enum.find_index(ids, fn el -> el == &1.id end)) total_entries: count,
total_pages: div(count + page_size - 1, page_size)
}
end
%{page | entries: records} def search_records(module, elastic_query, pagination_params \\ %{}, ecto_query \\ __MODULE__) do
end page = search_results(module, elastic_query, pagination_params)
end ids = page.entries
records =
ecto_query
|> where([m], m.id in ^ids)
|> Repo.all()
|> Enum.sort_by(&Enum.find_index(ids, fn el -> el == &1.id end))
%{page | entries: records}
end end
end end

View file

@ -0,0 +1,18 @@
defmodule Philomena.ElasticsearchIndex do
# Returns the index name for the index.
# This is usually a collection name like "images".
@callback index_name() :: String.t()
# Returns the document type for the index.
# This is usually the singular of the index name, like "image".
#
# TODO: Remove for ES 7.0
@callback doc_type() :: String.t()
# Returns the mapping and settings for the index.
@callback mapping() :: map()
# Returns the JSON representation of the given struct
# for indexing in Elasticsearch.
@callback as_json(struct()) :: map()
end

View file

@ -7,6 +7,7 @@ defmodule Philomena.Galleries do
alias Ecto.Multi alias Ecto.Multi
alias Philomena.Repo alias Philomena.Repo
alias Philomena.Elasticsearch
alias Philomena.Galleries.Gallery alias Philomena.Galleries.Gallery
alias Philomena.Galleries.Interaction alias Philomena.Galleries.Interaction
alias Philomena.Notifications alias Philomena.Notifications
@ -127,7 +128,7 @@ defmodule Philomena.Galleries do
|> preload(^indexing_preloads()) |> preload(^indexing_preloads())
|> where(id: ^gallery.id) |> where(id: ^gallery.id)
|> Repo.one() |> Repo.one()
|> Gallery.index_document() |> Elasticsearch.index_document(Gallery)
end end
gallery gallery
@ -135,7 +136,7 @@ defmodule Philomena.Galleries do
def unindex_gallery(%Gallery{} = gallery) do def unindex_gallery(%Gallery{} = gallery) do
spawn fn -> spawn fn ->
Gallery.delete_document(gallery.id) Elasticsearch.delete_document(gallery.id, Gallery)
end end
gallery gallery

View file

@ -1,4 +1,17 @@
defmodule Philomena.Galleries.Elasticsearch do defmodule Philomena.Galleries.ElasticsearchIndex do
@behaviour Philomena.ElasticsearchIndex
@impl true
def index_name do
"galleries"
end
@impl true
def doc_type do
"gallery"
end
@impl true
def mapping do def mapping do
%{ %{
settings: %{ settings: %{
@ -28,7 +41,7 @@ defmodule Philomena.Galleries.Elasticsearch do
} }
end end
# [:subscribers, :creator, :interactions] @impl true
def as_json(gallery) do def as_json(gallery) do
%{ %{
id: gallery.id, id: gallery.id,

View file

@ -2,11 +2,6 @@ defmodule Philomena.Galleries.Gallery do
use Ecto.Schema use Ecto.Schema
import Ecto.Changeset import Ecto.Changeset
use Philomena.Elasticsearch,
definition: Philomena.Galleries.Elasticsearch,
index_name: "galleries",
doc_type: "gallery"
alias Philomena.Images.Image alias Philomena.Images.Image
alias Philomena.Users.User alias Philomena.Users.User
alias Philomena.Galleries.Interaction alias Philomena.Galleries.Interaction

View file

@ -1,6 +1,7 @@
defmodule Philomena.ImageNavigator do defmodule Philomena.ImageNavigator do
alias Philomena.ImageSorter alias Philomena.ImageSorter
alias Philomena.Images.{Image, Elasticsearch} alias Philomena.Images.{Image, ElasticsearchIndex}
alias Philomena.Elasticsearch
alias Philomena.Repo alias Philomena.Repo
import Ecto.Query import Ecto.Query
@ -30,7 +31,7 @@ defmodule Philomena.ImageNavigator do
|> preload(:gallery_interactions) |> preload(:gallery_interactions)
|> Repo.one() |> Repo.one()
|> Map.merge(empty_fields()) |> Map.merge(empty_fields())
|> Elasticsearch.as_json() |> ElasticsearchIndex.as_json()
sort_data = ImageSorter.parse_sort(params) sort_data = ImageSorter.parse_sort(params)
@ -42,7 +43,8 @@ defmodule Philomena.ImageNavigator do
sorts = sortify(sorts, image_index) sorts = sortify(sorts, image_index)
filters = filterify(filters, image_index) filters = filterify(filters, image_index)
Image.search_records( Elasticsearch.search_records(
Image,
%{ %{
query: %{ query: %{
bool: %{ bool: %{

View file

@ -8,6 +8,7 @@ defmodule Philomena.Images do
alias Ecto.Multi alias Ecto.Multi
alias Philomena.Repo alias Philomena.Repo
alias Philomena.Elasticsearch
alias Philomena.Images.Image alias Philomena.Images.Image
alias Philomena.Images.Hider alias Philomena.Images.Hider
alias Philomena.Images.Uploader alias Philomena.Images.Uploader
@ -483,7 +484,7 @@ defmodule Philomena.Images do
Image Image
|> preload(^indexing_preloads()) |> preload(^indexing_preloads())
|> where([i], i.id in ^image_ids) |> where([i], i.id in ^image_ids)
|> Image.reindex() |> Elasticsearch.reindex(Image)
end end
image_ids image_ids

View file

@ -1,4 +1,17 @@
defmodule Philomena.Images.Elasticsearch do defmodule Philomena.Images.ElasticsearchIndex do
@behaviour Philomena.ElasticsearchIndex
@impl true
def index_name do
"images"
end
@impl true
def doc_type do
"image"
end
@impl true
def mapping do def mapping do
%{ %{
settings: %{ settings: %{
@ -77,10 +90,7 @@ defmodule Philomena.Images.Elasticsearch do
} }
end end
# preload([ @impl true
# :user, :deleter, :gallery_interactions, :upvoters, :downvoters, :favers,
# :hiders, tags: [:aliases, :aliased_tag]
# ])
def as_json(image) do def as_json(image) do
%{ %{
id: image.id, id: image.id,

View file

@ -1,11 +1,6 @@
defmodule Philomena.Images.Image do defmodule Philomena.Images.Image do
use Ecto.Schema use Ecto.Schema
use Philomena.Elasticsearch,
definition: Philomena.Images.Elasticsearch,
index_name: "images",
doc_type: "image"
import Ecto.Changeset import Ecto.Changeset
import Ecto.Query import Ecto.Query

View file

@ -7,6 +7,7 @@ defmodule Philomena.Posts do
alias Ecto.Multi alias Ecto.Multi
alias Philomena.Repo alias Philomena.Repo
alias Philomena.Elasticsearch
alias Philomena.Topics.Topic alias Philomena.Topics.Topic
alias Philomena.Topics alias Philomena.Topics
alias Philomena.Posts.Post alias Philomena.Posts.Post
@ -207,7 +208,7 @@ defmodule Philomena.Posts do
|> preload(^indexing_preloads()) |> preload(^indexing_preloads())
|> where(id: ^post.id) |> where(id: ^post.id)
|> Repo.one() |> Repo.one()
|> Post.index_document() |> Elasticsearch.index_document(Post)
end end
post post

View file

@ -1,4 +1,17 @@
defmodule Philomena.Posts.Elasticsearch do defmodule Philomena.Posts.ElasticsearchIndex do
@behaviour Philomena.ElasticsearchIndex
@impl true
def index_name do
"posts"
end
@impl true
def doc_type do
"post"
end
@impl true
def mapping do def mapping do
%{ %{
settings: %{ settings: %{
@ -36,7 +49,7 @@ defmodule Philomena.Posts.Elasticsearch do
} }
end end
# [:user, topic: :forum] @impl true
def as_json(post) do def as_json(post) do
%{ %{
id: post.id, id: post.id,

View file

@ -2,11 +2,6 @@ defmodule Philomena.Posts.Post do
use Ecto.Schema use Ecto.Schema
import Ecto.Changeset import Ecto.Changeset
use Philomena.Elasticsearch,
definition: Philomena.Posts.Elasticsearch,
index_name: "posts",
doc_type: "post"
alias Philomena.Users.User alias Philomena.Users.User
alias Philomena.Topics.Topic alias Philomena.Topics.Topic

View file

@ -6,6 +6,7 @@ defmodule Philomena.Reports do
import Ecto.Query, warn: false import Ecto.Query, warn: false
alias Philomena.Repo alias Philomena.Repo
alias Philomena.Elasticsearch
alias Philomena.Reports.Report alias Philomena.Reports.Report
alias Philomena.Polymorphic alias Philomena.Polymorphic
@ -128,7 +129,7 @@ defmodule Philomena.Reports do
|> preload([:user, :admin]) |> preload([:user, :admin])
|> Repo.all() |> Repo.all()
|> Polymorphic.load_polymorphic(reportable: [reportable_id: :reportable_type]) |> Polymorphic.load_polymorphic(reportable: [reportable_id: :reportable_type])
|> Enum.map(&Report.index_document/1) |> Enum.map(&Elasticsearch.index_document(&1, Report))
end end
report_ids report_ids

View file

@ -1,4 +1,17 @@
defmodule Philomena.Reports.Elasticsearch do defmodule Philomena.Reports.ElasticsearchIndex do
@behaviour Philomena.ElasticsearchIndex
@impl true
def index_name do
"reports"
end
@impl true
def doc_type do
"report"
end
@impl true
def mapping do def mapping do
%{ %{
settings: %{ settings: %{
@ -32,6 +45,7 @@ defmodule Philomena.Reports.Elasticsearch do
} }
end end
@impl true
def as_json(report) do def as_json(report) do
%{ %{
id: report.id, id: report.id,

View file

@ -2,11 +2,6 @@ defmodule Philomena.Reports.Report do
use Ecto.Schema use Ecto.Schema
import Ecto.Changeset import Ecto.Changeset
use Philomena.Elasticsearch,
definition: Philomena.Reports.Elasticsearch,
index_name: "reports",
doc_type: "report"
alias Philomena.Users.User alias Philomena.Users.User
schema "reports" do schema "reports" do

View file

@ -7,6 +7,7 @@ defmodule Philomena.Tags do
alias Ecto.Multi alias Ecto.Multi
alias Philomena.Repo alias Philomena.Repo
alias Philomena.Elasticsearch
alias Philomena.Tags.Tag alias Philomena.Tags.Tag
alias Philomena.Tags.Uploader alias Philomena.Tags.Uploader
alias Philomena.Images alias Philomena.Images
@ -165,12 +166,12 @@ defmodule Philomena.Tags do
{:ok, tag} = Repo.delete(tag) {:ok, tag} = Repo.delete(tag)
Tag.delete_document(tag.id) Elasticsearch.delete_document(tag.id, Tag)
Image Image
|> where([i], i.id in ^image_ids) |> where([i], i.id in ^image_ids)
|> preload(^Images.indexing_preloads()) |> preload(^Images.indexing_preloads())
|> Image.reindex() |> Elasticsearch.reindex(Image)
end end
def alias_tag(%Tag{} = tag, attrs) do def alias_tag(%Tag{} = tag, attrs) do
@ -234,7 +235,7 @@ defmodule Philomena.Tags do
|> join(:inner, [i], _ in assoc(i, :tags)) |> join(:inner, [i], _ in assoc(i, :tags))
|> where([_i, t], t.id == ^tag.id) |> where([_i, t], t.id == ^tag.id)
|> preload(^Images.indexing_preloads()) |> preload(^Images.indexing_preloads())
|> Image.reindex() |> Elasticsearch.reindex(Image)
end end
def unalias_tag(%Tag{} = tag) do def unalias_tag(%Tag{} = tag) do
@ -316,7 +317,7 @@ defmodule Philomena.Tags do
Tag Tag
|> preload(^indexing_preloads()) |> preload(^indexing_preloads())
|> where([t], t.id in ^ids) |> where([t], t.id in ^ids)
|> Tag.reindex() |> Elasticsearch.reindex(Tag)
end end
tags tags

View file

@ -1,4 +1,17 @@
defmodule Philomena.Tags.Elasticsearch do defmodule Philomena.Tags.ElasticsearchIndex do
@behaviour Philomena.ElasticsearchIndex
@impl true
def index_name do
"tags"
end
@impl true
def doc_type do
"tag"
end
@impl true
def mapping do def mapping do
%{ %{
settings: %{ settings: %{
@ -48,9 +61,7 @@ defmodule Philomena.Tags.Elasticsearch do
} }
end end
# preload([ @impl true
# :aliased_tag, :aliases, :implied_tags, :implied_by_tags
# ])
def as_json(tag) do def as_json(tag) do
%{ %{
id: tag.id, id: tag.id,

View file

@ -2,11 +2,6 @@ defmodule Philomena.Tags.Tag do
use Ecto.Schema use Ecto.Schema
import Ecto.Changeset import Ecto.Changeset
use Philomena.Elasticsearch,
definition: Philomena.Tags.Elasticsearch,
index_name: "tags",
doc_type: "tag"
alias Philomena.DnpEntries.DnpEntry alias Philomena.DnpEntries.DnpEntry
alias Philomena.UserLinks.UserLink alias Philomena.UserLinks.UserLink
alias Philomena.Tags.Tag alias Philomena.Tags.Tag

View file

@ -2,6 +2,7 @@ defmodule PhilomenaWeb.ActivityController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias PhilomenaWeb.ImageLoader alias PhilomenaWeb.ImageLoader
alias Philomena.Elasticsearch
alias Philomena.{Images.Image, ImageFeatures.ImageFeature, Comments.Comment, Channels.Channel, Topics.Topic, Forums.Forum} alias Philomena.{Images.Image, ImageFeatures.ImageFeature, Comments.Comment, Channels.Channel, Topics.Topic, Forums.Forum}
alias Philomena.Interactions alias Philomena.Interactions
alias Philomena.Repo alias Philomena.Repo
@ -26,7 +27,8 @@ defmodule PhilomenaWeb.ActivityController do
) )
comments = comments =
Comment.search_records( Elasticsearch.search_records(
Comment,
%{ %{
query: %{ query: %{
bool: %{ bool: %{

View file

@ -1,6 +1,7 @@
defmodule PhilomenaWeb.Admin.ReportController do defmodule PhilomenaWeb.Admin.ReportController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias Philomena.Elasticsearch
alias Philomena.Textile.Renderer alias Philomena.Textile.Renderer
alias Philomena.Reports.Report alias Philomena.Reports.Report
alias Philomena.Reports.Query alias Philomena.Reports.Query
@ -61,7 +62,8 @@ defmodule PhilomenaWeb.Admin.ReportController do
defp load_reports(conn, query) do defp load_reports(conn, query) do
reports = reports =
Report.search_records( Elasticsearch.search_records(
Report,
%{ %{
query: query, query: query,
sort: sorts() sort: sorts()

View file

@ -2,6 +2,7 @@ defmodule PhilomenaWeb.Api.Json.Search.CommentController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias PhilomenaWeb.CommentJson alias PhilomenaWeb.CommentJson
alias Philomena.Elasticsearch
alias Philomena.Comments.Comment alias Philomena.Comments.Comment
alias Philomena.Comments.Query alias Philomena.Comments.Query
import Ecto.Query import Ecto.Query
@ -13,7 +14,8 @@ defmodule PhilomenaWeb.Api.Json.Search.CommentController do
case Query.compile(user, params["q"] || "") do case Query.compile(user, params["q"] || "") do
{:ok, query} -> {:ok, query} ->
comments = comments =
Comment.search_records( Elasticsearch.search_records(
Comment,
%{ %{
query: %{ query: %{
bool: %{ bool: %{

View file

@ -2,6 +2,7 @@ defmodule PhilomenaWeb.Api.Json.Search.GalleryController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias PhilomenaWeb.GalleryJson alias PhilomenaWeb.GalleryJson
alias Philomena.Elasticsearch
alias Philomena.Galleries.Gallery alias Philomena.Galleries.Gallery
alias Philomena.Galleries.Query alias Philomena.Galleries.Query
import Ecto.Query import Ecto.Query
@ -10,7 +11,8 @@ defmodule PhilomenaWeb.Api.Json.Search.GalleryController do
case Query.compile(params["q"] || "") do case Query.compile(params["q"] || "") do
{:ok, query} -> {:ok, query} ->
galleries = galleries =
Gallery.search_records( Elasticsearch.search_records(
Gallery,
%{ %{
query: query, query: query,
sort: %{created_at: :desc} sort: %{created_at: :desc}

View file

@ -2,6 +2,7 @@ defmodule PhilomenaWeb.Api.Json.Search.PostController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias PhilomenaWeb.PostJson alias PhilomenaWeb.PostJson
alias Philomena.Elasticsearch
alias Philomena.Posts.Post alias Philomena.Posts.Post
alias Philomena.Posts.Query alias Philomena.Posts.Query
import Ecto.Query import Ecto.Query
@ -12,7 +13,8 @@ defmodule PhilomenaWeb.Api.Json.Search.PostController do
case Query.compile(user, params["q"] || "") do case Query.compile(user, params["q"] || "") do
{:ok, query} -> {:ok, query} ->
posts = posts =
Post.search_records( Elasticsearch.search_records(
Post,
%{ %{
query: %{ query: %{
bool: %{ bool: %{

View file

@ -2,6 +2,7 @@ defmodule PhilomenaWeb.Api.Json.Search.TagController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias PhilomenaWeb.TagJson alias PhilomenaWeb.TagJson
alias Philomena.Elasticsearch
alias Philomena.Tags.Tag alias Philomena.Tags.Tag
alias Philomena.Tags.Query alias Philomena.Tags.Query
import Ecto.Query import Ecto.Query
@ -10,7 +11,8 @@ defmodule PhilomenaWeb.Api.Json.Search.TagController do
case Query.compile(params["q"] || "") do case Query.compile(params["q"] || "") do
{:ok, query} -> {:ok, query} ->
tags = tags =
Tag.search_records( Elasticsearch.search_records(
Tag,
%{query: query, sort: %{images: :desc}}, %{query: query, sort: %{images: :desc}},
conn.assigns.pagination, conn.assigns.pagination,
preload(Tag, [:aliased_tag, :aliases, :implied_tags, :implied_by_tags, :dnp_entries]) preload(Tag, [:aliased_tag, :aliases, :implied_tags, :implied_by_tags, :dnp_entries])

View file

@ -1,34 +1,11 @@
defmodule PhilomenaWeb.Api.Rss.WatchedController do defmodule PhilomenaWeb.Api.Rss.WatchedController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias Philomena.Images.{Image, Query} alias PhilomenaWeb.ImageLoader
import Ecto.Query
def index(conn, _params) do def index(conn, _params) do
user = conn.assigns.current_user {:ok, {images, _tags}} = ImageLoader.search_string(conn, "my:watched")
filter = conn.assigns.compiled_filter
{:ok, query} = Query.compile(user, "my:watched") render(conn, "index.rss", images: images)
images =
Image.search_records(
%{
query: %{
bool: %{
must: query,
must_not: [
filter,
%{term: %{hidden_from_users: true}}
]
}
},
sort: %{created_at: :desc}
},
conn.assigns.image_pagination,
Image |> preload(:tags)
)
conn
|> render("index.rss", images: images)
end end
end end

View file

@ -1,6 +1,7 @@
defmodule PhilomenaWeb.CommentController do defmodule PhilomenaWeb.CommentController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias Philomena.Elasticsearch
alias Philomena.{Comments.Query, Comments.Comment, Textile.Renderer} alias Philomena.{Comments.Query, Comments.Comment, Textile.Renderer}
import Ecto.Query import Ecto.Query
@ -18,7 +19,8 @@ defmodule PhilomenaWeb.CommentController do
defp render_index({:ok, query}, conn, user) do defp render_index({:ok, query}, conn, user) do
comments = comments =
Comment.search_records( Elasticsearch.search_records(
Comment,
%{ %{
query: %{ query: %{
bool: %{ bool: %{

View file

@ -3,6 +3,7 @@ defmodule PhilomenaWeb.GalleryController do
alias PhilomenaWeb.ImageLoader alias PhilomenaWeb.ImageLoader
alias PhilomenaWeb.NotificationCountPlug alias PhilomenaWeb.NotificationCountPlug
alias Philomena.Elasticsearch
alias Philomena.ImageSorter alias Philomena.ImageSorter
alias Philomena.Interactions alias Philomena.Interactions
alias Philomena.Galleries.Gallery alias Philomena.Galleries.Gallery
@ -14,7 +15,8 @@ defmodule PhilomenaWeb.GalleryController do
def index(conn, params) do def index(conn, params) do
galleries = galleries =
Gallery.search_records( Elasticsearch.search_records(
Gallery,
%{ %{
query: %{ query: %{
bool: %{ bool: %{

View file

@ -1,6 +1,7 @@
defmodule PhilomenaWeb.Image.RandomController do defmodule PhilomenaWeb.Image.RandomController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias Philomena.Elasticsearch
alias Philomena.Images.Query alias Philomena.Images.Query
alias Philomena.Images.Image alias Philomena.Images.Image
alias Philomena.ImageSorter alias Philomena.ImageSorter
@ -30,7 +31,8 @@ defmodule PhilomenaWeb.Image.RandomController do
defp random_image_id(query, filter) do defp random_image_id(query, filter) do
sort = ImageSorter.parse_sort(%{"sf" => "random"}) sort = ImageSorter.parse_sort(%{"sf" => "random"})
Image.search_records( Elasticsearch.search_records(
Image,
%{ %{
query: %{ query: %{
bool: %{ bool: %{

View file

@ -1,6 +1,7 @@
defmodule PhilomenaWeb.PostController do defmodule PhilomenaWeb.PostController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias Philomena.Elasticsearch
alias Philomena.{Posts.Query, Posts.Post, Textile.Renderer} alias Philomena.{Posts.Query, Posts.Post, Textile.Renderer}
import Ecto.Query import Ecto.Query
@ -18,7 +19,8 @@ defmodule PhilomenaWeb.PostController do
defp render_index({:ok, query}, conn, user) do defp render_index({:ok, query}, conn, user) do
posts = posts =
Post.search_records( Elasticsearch.search_records(
Post,
%{ %{
query: %{ query: %{
bool: %{ bool: %{

View file

@ -2,6 +2,7 @@ defmodule PhilomenaWeb.ProfileController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias PhilomenaWeb.ImageLoader alias PhilomenaWeb.ImageLoader
alias Philomena.Elasticsearch
alias Philomena.Textile.Renderer alias Philomena.Textile.Renderer
alias Philomena.UserStatistics.UserStatistic alias Philomena.UserStatistics.UserStatistic
alias Philomena.Users.User alias Philomena.Users.User
@ -61,7 +62,8 @@ defmodule PhilomenaWeb.ProfileController do
recent_artwork = recent_artwork(conn, tags) recent_artwork = recent_artwork(conn, tags)
recent_comments = recent_comments =
Comment.search_records( Elasticsearch.search_records(
Comment,
%{ %{
query: %{ query: %{
bool: %{ bool: %{
@ -88,7 +90,8 @@ defmodule PhilomenaWeb.ProfileController do
|> Enum.zip(recent_comments) |> Enum.zip(recent_comments)
recent_posts = recent_posts =
Post.search_records( Elasticsearch.search_records(
Post,
%{ %{
query: %{ query: %{
bool: %{ bool: %{

View file

@ -1,6 +1,7 @@
defmodule PhilomenaWeb.StatController do defmodule PhilomenaWeb.StatController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias Philomena.Elasticsearch
alias Philomena.Images.Image alias Philomena.Images.Image
alias Philomena.Comments.Comment alias Philomena.Comments.Comment
alias Philomena.Topics.Topic alias Philomena.Topics.Topic
@ -51,7 +52,10 @@ defmodule PhilomenaWeb.StatController do
Application.get_env(:philomena, :aggregation_json) Application.get_env(:philomena, :aggregation_json)
|> Jason.decode!() |> Jason.decode!()
{Image.search(data["images"]), Comment.search(data["comments"])} {
Elasticsearch.search(Image, data["images"]),
Elasticsearch.search(Comment, data["comments"])
}
end end
defp forums do defp forums do

View file

@ -1,6 +1,7 @@
defmodule PhilomenaWeb.Tag.AutocompleteController do defmodule PhilomenaWeb.Tag.AutocompleteController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias Philomena.Elasticsearch
alias Philomena.Tags.Tag alias Philomena.Tags.Tag
def show(conn, params) do def show(conn, params) do
@ -10,7 +11,8 @@ defmodule PhilomenaWeb.Tag.AutocompleteController do
[] []
term -> term ->
Tag.search_records( Elasticsearch.search_records(
Tag,
%{ %{
query: %{ query: %{
bool: %{ bool: %{

View file

@ -2,6 +2,7 @@ defmodule PhilomenaWeb.TagController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias PhilomenaWeb.ImageLoader alias PhilomenaWeb.ImageLoader
alias Philomena.Elasticsearch
alias Philomena.{Tags, Tags.Tag} alias Philomena.{Tags, Tags.Tag}
alias Philomena.Textile.Renderer alias Philomena.Textile.Renderer
alias Philomena.Interactions alias Philomena.Interactions
@ -16,7 +17,8 @@ defmodule PhilomenaWeb.TagController do
with {:ok, query} <- Tags.Query.compile(query_string) do with {:ok, query} <- Tags.Query.compile(query_string) do
tags = tags =
Tag.search_records( Elasticsearch.search_records(
Tag,
%{ %{
query: query, query: query,
size: 250, size: 250,

View file

@ -19,7 +19,7 @@ defmodule PhilomenaWeb.ImageJson do
tag_ids: Enum.map(image.tags, & &1.id), tag_ids: Enum.map(image.tags, & &1.id),
uploader: if(!!image.user and !image.anonymous, do: image.user.name), uploader: if(!!image.user and !image.anonymous, do: image.user.name),
uploader_id: if(!!image.user and !image.anonymous, do: image.user.id), uploader_id: if(!!image.user and !image.anonymous, do: image.user.id),
wilson_score: Philomena.Images.Elasticsearch.wilson_score(image), wilson_score: Philomena.Images.ElasticsearchIndex.wilson_score(image),
score: image.score, score: image.score,
upvotes: image.upvotes_count, upvotes: image.upvotes_count,
downvotes: image.downvotes_count, downvotes: image.downvotes_count,

View file

@ -1,4 +1,5 @@
defmodule PhilomenaWeb.ImageLoader do defmodule PhilomenaWeb.ImageLoader do
alias Philomena.Elasticsearch
alias Philomena.Images.{Image, Query} alias Philomena.Images.{Image, Query}
alias Philomena.Textile.Renderer alias Philomena.Textile.Renderer
alias Philomena.Tags.Tag alias Philomena.Tags.Tag
@ -27,7 +28,8 @@ defmodule PhilomenaWeb.ImageLoader do
filters = create_filters(conn, user, filter) filters = create_filters(conn, user, filter)
records = records =
Image.search_records( Elasticsearch.search_records(
Image,
%{ %{
query: %{ query: %{
bool: %{ bool: %{

View file

@ -2,6 +2,7 @@ defmodule PhilomenaWeb.TagView do
use PhilomenaWeb, :view use PhilomenaWeb, :view
# this is bad practice, don't copy this. # this is bad practice, don't copy this.
alias Philomena.Elasticsearch
alias Philomena.Tags.Tag alias Philomena.Tags.Tag
alias Philomena.Repo alias Philomena.Repo
import Ecto.Query import Ecto.Query
@ -124,7 +125,8 @@ defmodule PhilomenaWeb.TagView do
end end
defp implied_by_multitag(tag_names, ignore_tag_names) do defp implied_by_multitag(tag_names, ignore_tag_names) do
Tag.search_records( Elasticsearch.search_records(
Tag,
%{ %{
query: %{ query: %{
bool: %{ bool: %{