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]
19 "/indexes/objects/settings/ranking-rules",
33 "/indexes/objects/settings/searchable-attributes",
39 IO.puts("Created indices. Starting to insert posts.")
41 chunk_size = Pleroma.Config.get([Pleroma.Search.Meilisearch, :initial_indexing_chunk_size])
43 Pleroma.Repo.transaction(
47 # Only index public and unlisted posts which are notes and have some text
49 fragment("data->>'type' = 'Note'") and
50 (fragment("data->'to' \\? ?", ^Pleroma.Constants.as_public()) or
51 fragment("data->'cc' \\? ?", ^Pleroma.Constants.as_public())),
52 order_by: [desc: fragment("data->'published'")]
55 count = query |> Pleroma.Repo.aggregate(:count, :data)
56 IO.puts("Entries to index: #{count}")
62 |> Stream.map(&Pleroma.Search.Meilisearch.object_to_search_data/1)
63 |> Stream.filter(fn o -> not is_nil(o) end)
64 |> Stream.chunk_every(chunk_size)
65 |> Stream.transform(0, fn objects, acc ->
66 new_acc = acc + Enum.count(objects)
68 # Reset to the beginning of the line and rewrite it
70 IO.write("Indexed #{new_acc} entries")
74 |> Stream.each(fn objects ->
77 "/indexes/objects/documents",
81 with {:ok, res} <- result do
82 if not Map.has_key?(res, "updateId") do
83 IO.puts("\nFailed to index: #{inspect(result)}")
86 e -> IO.puts("\nFailed to index due to network error: #{inspect(e)}")
100 meili_delete!("/indexes/objects/documents")
103 def run(["show-private-key", master_key]) do
106 endpoint = Pleroma.Config.get([Pleroma.Search.Meilisearch, :url])
110 Path.join(endpoint, "/keys"),
111 [{"X-Meili-API-Key", master_key}]
114 decoded = Jason.decode!(result.body)
116 if decoded["private"] do
117 IO.puts(decoded["private"])
119 IO.puts("Error fetching the key, check the master key is correct: #{inspect(decoded)}")
123 def run(["stats"]) do
126 {:ok, result} = meili_get("/indexes/objects/stats")
127 IO.puts("Number of entries: #{result["numberOfDocuments"]}")
128 IO.puts("Indexing? #{result["isIndexing"]}")