120 lines
2.3 KiB
Elixir
120 lines
2.3 KiB
Elixir
defmodule Pleroma.Elasticsearch do
|
|
alias Pleroma.Activity
|
|
alias Pleroma.Elasticsearch.DocumentMappings
|
|
|
|
@searchable [
|
|
"hashtag", "instance", "user"
|
|
]
|
|
|
|
defp url do
|
|
Pleroma.Config.get([:elasticsearch, :url])
|
|
end
|
|
|
|
def put(%Activity{} = activity) do
|
|
Elastix.Document.index(
|
|
url(),
|
|
"activities",
|
|
"activity",
|
|
DocumentMappings.Activity.id(activity),
|
|
DocumentMappings.Activity.encode(activity)
|
|
)
|
|
end
|
|
|
|
def bulk_post(data, :activities) do
|
|
d = data
|
|
|> Enum.map(fn d ->
|
|
[
|
|
%{index: %{_id: DocumentMappings.Activity.id(d)}},
|
|
DocumentMappings.Activity.encode(d)
|
|
]
|
|
end)
|
|
|> List.flatten()
|
|
|
|
Elastix.Bulk.post(
|
|
url(),
|
|
d,
|
|
index: "activities",
|
|
type: "activity"
|
|
)
|
|
end
|
|
|
|
defp parse_term(t) do
|
|
if String.contains?(t, ":") and !String.starts_with?(t, "\"") do
|
|
[field, query] = String.split(t, ":")
|
|
if Enum.member?(@searchable, field) do
|
|
{field, query}
|
|
else
|
|
{"content", query}
|
|
end
|
|
else
|
|
{"content", t}
|
|
end
|
|
end
|
|
|
|
defp search_user(params, q) do
|
|
if q["user"] != nil do
|
|
params ++ [%{match: %{user: %{
|
|
query: Enum.join(q["user"], " "),
|
|
operator: "OR"
|
|
}}}]
|
|
else
|
|
params
|
|
end
|
|
end
|
|
|
|
defp search_instance(params, q) do
|
|
if q["instance"] != nil do
|
|
params ++ [%{match: %{instance: %{
|
|
query: Enum.join(q["instance"], " "),
|
|
operator: "OR"
|
|
}}}]
|
|
else
|
|
params
|
|
end
|
|
end
|
|
|
|
defp search_content(params, q) do
|
|
if q["content"] != nil do
|
|
params ++ [%{match: %{content: %{
|
|
query: Enum.join(q["content"], " "),
|
|
operator: "AND"
|
|
}}}]
|
|
else
|
|
params
|
|
end
|
|
end
|
|
|
|
defp to_es(q) do
|
|
[]
|
|
|> search_content(q)
|
|
|> search_instance(q)
|
|
|> search_user(q)
|
|
end
|
|
|
|
defp parse(query) do
|
|
String.split(query, " ")
|
|
|> Enum.map(&parse_term/1)
|
|
|> Enum.reduce(%{}, fn {field, query}, acc ->
|
|
Map.put(acc, field,
|
|
Map.get(acc, field, []) ++ [query]
|
|
)
|
|
end)
|
|
|> to_es()
|
|
end
|
|
|
|
def search(query) do
|
|
q = %{query: %{
|
|
bool: %{
|
|
must: parse(query)
|
|
}
|
|
}}
|
|
IO.inspect(q)
|
|
Elastix.Search.search(
|
|
url(),
|
|
"activities",
|
|
["activity"],
|
|
q
|
|
)
|
|
end
|
|
end
|