Discourses API get just the number of search results

Hi. I am trying to get just the number of search results from the API.
I have the following query /search.json?q=query but i just need information about how many results there are. Not blurbs, cooked, etc.
Is it possible with discourse API?

I don’t think we return a “count” in the response, but it is something you can calculate yourself.

See the search API docs for a more detailed response example, but it will look something like this:

{
    "posts": [],
    "topics": [],
    "users": [],
    "categories": [],
    "grouped_search_result": {}
}

Be default the API will return a max of 50 results. To calculate the count you need to just count the number of items in the posts array. The number items in the topics array should be the same so there is no reason to count that array too.

Я перепробовал все мыслимые способы, чтобы просто скачать все темы и посты с моего сайта — разделы «Последние» и «Лучшие» ограничены, и теперь я пытаюсь получить все категории, а затем выполнять поиск по категории (по аналогии с тем, как это можно сделать на самом сайте). Например, если на нашем сайте я ищу «Q&A #q-a» здесь, то получаю более 50 результатов. Когда я ищу эту же строку с помощью ruby-библиотеки discourse_api, получаю только 5:

irb(main):123:0> topics["posts"].length
=> 5
irb(main):124:0> topics["topics"].length
=> 5

Почему это не согласуется с интерфейсом и с тем, о чём вы сообщаете? Какой самый простой способ экспорта данных? Я хотел бы провести NLP-анализ контента нашего сайта, но даже получение данных оказывается очень сложной задачей. Спасибо!

Последние посты поддерживают пагинацию, вам просто нужно правильно передать параметры, и вы сможете получить доступ ко всем темам через API.

Поиск также поддерживает пагинацию.

Я рекомендую Reverse engineer the Discourse API в качестве быстрого руководства для понимания всех необходимых параметров.

Спасибо, @sam! Я вижу (даже из GET-запроса), что это должно быть довольно интуитивно понятно: когда я хочу получить страницу 2, я добавляю дополнительный параметр page. Я также вижу, что «options» — это то, что я могу определить с помощью функции discourse_api:

# frozen_string_literal: true
module DiscourseApi
  module API
    module Search
      # Возвращает результаты поиска, соответствующие указанному термину.
      #
      # @param term [String] поисковый термин
      # @param options [Hash] набор настраиваемых опций
      # @option options [String] :type_filter Возвращает результаты указанного типа.
      # @return [Array] Возвращает результаты в виде массива хешей.
      def search(term, options = {})
        raise ArgumentError.new("#{term} требуется, но не указан") unless term
        raise ArgumentError.new("#{term} требуется, но не указан") unless !term.empty?

        response = get('/search/query', options.merge(term: term))
        response[:body]
      end
    end
  end
end

Итак, попробуем это применить: я ожидаю получить разные результаты для страницы 1 и страницы 2. Или давайте сделаем чуть больше разделения и возьмём страницы 1 и 3. Запрос касается всех тем Q&A:

 query = category["name"] + " #" + category["slug"]
=> "Q&A #q-a"

Теперь получим страницы 1 и 3 с помощью клиента discourse_api:

topics1 = client.search(query, options={"page": "1"})
topics3 = client.search(query, options={"page": "3"})

Я могу посмотреть на первую тему в каждом случае:

=> {"id"=>220, "title"=>"Why am I exceeding the quota?", "fancy_title"=>"Why am I exceeding the quota?", "slug"=>"why-am-i-exceeding-the-quota", "posts_count"=>3, "reply_count"=>0, "highest_post_number"=>3, "image_url"=>nil, "created_at"=>"2018-06-01T12:56:12.120Z", "last_posted_at"=>"2018-06-15T16:41:44.736Z", "bumped"=>true, "bumped_at"=>"2018-06-15T16:41:44.736Z", "unseen"=>false, "pinned"=>false, "unpinned"=>nil, "visible"=>true, "closed"=>false, "archived"=>false, "bookmarked"=>nil, "liked"=>nil, "tags"=>["storage", "quota"], "category_id"=>26, "has_accepted_answer"=>false}

irb(main):148:0> topics3['topics'][0]
=> {"id"=>220, "title"=>"Why am I exceeding the quota?", "fancy_title"=>"Why am I exceeding the quota?", "slug"=>"why-am-i-exceeding-the-quota", "posts_count"=>3, "reply_count"=>0, "highest_post_number"=>3, "image_url"=>nil, "created_at"=>"2018-06-01T12:56:12.120Z", "last_posted_at"=>"2018-06-15T16:41:44.736Z", "bumped"=>true, "bumped_at"=>"2018-06-15T16:41:44.736Z", "unseen"=>false, "pinned"=>false, "unpinned"=>nil, "visible"=>true, "closed"=>false, "archived"=>false, "bookmarked"=>nil, "liked"=>nil, "tags"=>["storage", "quota"], "category_id"=>26, "has_accepted_answer"=>false}

Они абсолютно одинаковы, что, как мне кажется, означает, что переменная page не работает? Когда я проверяю это в инструментах разработчика Chrome, событие срабатывает при прокрутке вниз (поскольку посты автоматически загружаются в окне), и я могу подтвердить, что page=2 — это правильный параметр:

Request URL: https://ask.cyberinfrastructure.org/search?q=Q%26A%20%23q-a&page=2
Request Method: GET
Status Code: 200  (from ServiceWorker)
Referrer Policy: strict-origin-when-cross-origin

Или ещё лучше, просто посмотрите на список параметров:

Query String Parameters
q: Q&A #q-a
page: 2

Это не отправка формы, поэтому я не вижу никаких «Form Data», как в примере.

Есть ли здесь кто-нибудь, кто может подсказать? Я попробовал то, что было предложено, но не вижу логичного следующего шага. Переменная page, похоже, не работает при передаче в запросе.

Гем Discourse API использует маршрут /search/query. Он не поддерживает пагинацию. Интерфейс Discourse использует маршрут /search. Он поддерживает пагинацию.

Вы можете протестировать это в браузере, перейдя по адресу http://forum.example.com/search.json?q=test, а затем попробовав http://forum.example.com/search.json?q=test&page=2.

Возможно, вам придётся найти способ выполнить API-вызов без использования гема Discourse API. Если ваша цель — получить все темы и сообщения на вашем сайте, использование маршрута /search кажется не самым лучшим решением.

Попробуйте выполнить API-вызов по адресу http://forum.example.com/c/your-category-slug.json. Если в ответе запроса не возвращаются все темы категории, свойство topic_list запроса будет содержать свойство more_topics_url, которое укажет путь к следующей странице тем. Это будет выглядеть примерно так: "/c/site-feedback?page=2". Вам нужно будет добавить .json к URL, чтобы получить данные в формате JSON (/c/site-feedback.json?page=2).

Спасибо! Это сработало абсолютно идеально, и в Python с библиотекой requests это намного проще (я намеренно усложнял задачу, чтобы лучше разобраться с Ruby, но в клиенте не было нужных мне функций). Я в основном завершил экспорт и ещё не занимался машинным обучением, но если кому-то интересно, какие вызовы я использовал, быстрые скрипты доступны здесь: GitHub - hpsee/discourse-cluster: Simple scripts to export posts for a discourse category, and do a clustering · GitHub. Надеюсь, скоро займусь интересной кластеризацией!

Ещё раз спасибо @sam и @simon — на случай, если кому-то из других захочется сделать простой экспорт тем или (пойти дальше) и провести кластеризацию с визуализацией в d3, я написал краткий пост, который всё это объясняет: AskCI Discourse Clustering | VanessaSaurus. И ещё раз: все необходимые материалы для начала работы находятся в репозитории, на который я ссылался ранее.