1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Mix.Tasks.Pleroma.Search.Meilisearch do
6 require Pleroma.Constants
11 import Pleroma.Search.Meilisearch,
12 only: [meili_post: 2, meili_put: 2, meili_get: 1, meili_delete: 1]
16 Pleroma.HTML.compile_scrubbers()
20 {:ok, result} = meili_get("/version")
25 # The ranking rule syntax was changed but nothing about that is mentioned in the changelog
26 if not Version.match?(meili_version, ">= 0.25.0") do
27 raise "Meilisearch <0.24.0 not supported"
32 "/indexes/objects/settings/ranking-rules",
46 "/indexes/objects/settings/searchable-attributes",
52 IO.puts("Created indices. Starting to insert posts.")
54 chunk_size = Pleroma.Config.get([Pleroma.Search.Meilisearch, :initial_indexing_chunk_size])
56 Pleroma.Repo.transaction(
60 # Only index public and unlisted posts which are notes and have some text
62 fragment("data->>'type' = 'Note'") and
63 (fragment("data->'to' \\? ?", ^Pleroma.Constants.as_public()) or
64 fragment("data->'cc' \\? ?", ^Pleroma.Constants.as_public())),
65 order_by: [desc: fragment("data->'published'")]
68 count = query |> Pleroma.Repo.aggregate(:count, :data)
69 IO.puts("Entries to index: #{count}")
75 |> Stream.map(&Pleroma.Search.Meilisearch.object_to_search_data/1)
76 |> Stream.filter(fn o -> not is_nil(o) end)
77 |> Stream.chunk_every(chunk_size)
78 |> Stream.transform(0, fn objects, acc ->
79 new_acc = acc + Enum.count(objects)
81 # Reset to the beginning of the line and rewrite it
83 IO.write("Indexed #{new_acc} entries")
87 |> Stream.each(fn objects ->
90 "/indexes/objects/documents",
94 with {:ok, res} <- result do
95 if not Map.has_key?(res, "uid") do
96 IO.puts("\nFailed to index: #{inspect(result)}")
99 e -> IO.puts("\nFailed to index due to network error: #{inspect(e)}")
110 def run(["clear"]) do
113 meili_delete("/indexes/objects/documents")
116 def run(["show-keys", master_key]) do
119 endpoint = Pleroma.Config.get([Pleroma.Search.Meilisearch, :url])
123 Path.join(endpoint, "/keys"),
124 [{"Authorization", "Bearer #{master_key}"}]
127 decoded = Jason.decode!(result.body)
129 if decoded["results"] do
130 Enum.each(decoded["results"], fn %{"description" => desc, "key" => key} ->
131 IO.puts("#{desc}: #{key}")
134 IO.puts("Error fetching the keys, check the master key is correct: #{inspect(decoded)}")
138 def run(["stats"]) do
141 {:ok, result} = meili_get("/indexes/objects/stats")
142 IO.puts("Number of entries: #{result["numberOfDocuments"]}")
143 IO.puts("Indexing? #{result["isIndexing"]}")