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_put: 2, meili_get: 1, meili_delete!: 1]
19 {:ok, result} = meili_get("/version")
24 # The ranking rule syntax was changed but nothing about that is mentioned in the changelog
25 if not Version.match?(meili_version, ">= 0.25.0") do
26 raise "Meilisearch <0.24.0 not supported"
31 "/indexes/objects/settings/ranking-rules",
45 "/indexes/objects/settings/searchable-attributes",
51 IO.puts("Created indices. Starting to insert posts.")
53 chunk_size = Pleroma.Config.get([Pleroma.Search.Meilisearch, :initial_indexing_chunk_size])
55 Pleroma.Repo.transaction(
59 # Only index public and unlisted posts which are notes and have some text
61 fragment("data->>'type' = 'Note'") and
62 (fragment("data->'to' \\? ?", ^Pleroma.Constants.as_public()) or
63 fragment("data->'cc' \\? ?", ^Pleroma.Constants.as_public())) and
64 fragment("data->>'published' IS NOT NULL"),
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, "indexUid") 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"]}")