Как отфильтровать несколько записей и получить только самые внешние записи из структуры postgres ltree? - PullRequest
3 голосов
/ 05 февраля 2020

У меня есть записи базы данных, организованные в структуру ltree (Postgres расширение дерева).

Я хочу отфильтровать эти элементы до самых внешних предков текущего выбора.

Тестовые случаи:

 [11, 111, 1111, 2, 22, 222, 2221, 2222]                   => [11, 2];
 [1, 11, 111, 1111, 1112, 2, 22, 222, 2221, 2222, 3, 4, 5] => [1, 2, 3, 4, 5];
 [1111, 1112, 2221, 2222]                                  => [1111, 1112, 2221, 2222];
  1
  |_1.1
  | |_1.1.1
  |   |_1.1.1.1
  |   |_1.1.1.2
  2
  |_2.2
  | |_2.2.2
  |   |_2.2.2.1
  |   |_2.2.2.2
  3
  |
  4
  |
  5

Я реализовал это в Ruby примерно так.

  def fetch_outer_most_items(identifiers)
    ordered_items = Item.where(id: identifiers).order("path DESC")
    items_array = ordered_items.to_a
    outer_most_item_ids = []

    while(items_array.size > 0) do
      item = items_array.pop
      outer_most_item_ids.push(item.id)
      duplicate_ids = ordered_items.where("items.path <@ '#{item.path}'").pluck(:id)

      if duplicate_ids.any?
        items_array = items_array.select { |i| !duplicate_ids.include?(i.id) }
      end
    end

    return ordered_items.where(id: outer_most_item_ids)
  end

Я удалил потомков как дубликаты с помощью рекурсии. Я почти уверен, что есть способ SQL, который будет предпочтительным решением, так как этот запускает n + 1 запросов. В идеале я бы добавил эту функцию в качестве именованной области видимости для модели Item.

Любые указатели, пожалуйста?

...