Существует несколько способов решения этой проблемы:
Отображение всех результатов с бесконечной загрузкой
onAllData
даст количество результатов, указанное в size
проп. Обычно не очень хорошая идея устанавливать очень высокое значение size
, так как это займет больше времени для извлечения и рендеринга результатов. Хорошей альтернативой для этого является использование бесконечной прокрутки, установив pagination
prop в false
и установив значение в size
prop, которое сообщает компоненту, сколько результатов нужно извлечь, когда вы достигнете конца списка.
Получение всех результатов с помощью API прокрутки
Примечание
В этом ответе используется реактивный поиск для веб-сайтов (для демонстрации), но вы можете использовать те же реквизиты в реактивном поиске, поскольку API такой же.
Приведенный выше подход работает нормально, если вы заинтересованы только в рендеринге результатов. Но если вы хотите получить все результаты для текущего запроса, вы можете использовать API scroll от Elasticsearch. Вы можете использовать ReactiveList
, чтобы получить текущий запрос, а затем использовать его вместе с API прокрутки.
Для этой цели вы можете использовать onQueryChange
опору на ReactiveList
:
Сначала укажите onQueryChange
реквизит ReactiveList
, который получает предыдущий и текущий запрос в качестве параметров:
onQueryChange={(prev, next) => ...}
Эта функция будет вызываться при каждом изменении запроса, поэтому вы можете написать логику для выборки совпадений для текущего запроса (полученного в параметре next
) всякий раз, когда потребуется.
Вызов API прокрутки возвращает результаты в следующем формате:
{
"_scroll_id": "DnF1ZXJ5VGhlbkZldGNoAgAAAAClGlY4FlotbmJJZXA0U09lMlZFMUNyQ3M2M0EAAAAApRpWORZaLW5iSWVwNFNPZTJWRTFDckNzNjNB",
"took": 0,
"timed_out": false,
"_shards": {
"total": 2,
"successful": 2,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 9407,
"max_score": 1,
"hits": [
{
"_index": "good-books-ds",
"_type": "good-books-ds",
"_id": "5676",
"_score": 1,
"_source": {
"authors": "Arthur C. Clarke, Gentry Lee",
"average_rating": 3.76,
"average_rating_rounded": 4,
"books_count": 48,
"id": 5676,
"image": "https://images.gr-assets.com/books/1375814957l/112518.jpg",
"image_medium": "https://images.gr-assets.com/books/1375814957m/112518.jpg",
"isbn": "1857230213",
"language_code": "eng",
"original_publication_year": 1991,
"original_series": "Rama",
"original_title": "The Garden of Rama (Rama, #3)",
"ratings_count": 16389,
"title": "The Garden of Rama (Rama, #3)"
}
},
{
"_index": "good-books-ds",
"_type": "good-books-ds",
"_id": "5681",
"_score": 1,
"_source": {
"authors": "Darren Shan",
"average_rating": 4.22,
"average_rating_rounded": 4,
"books_count": 52,
"id": 5681,
"image": "https://s.gr-assets.com/assets/nophoto/book/111x148-bcc042a9c91a29c1d680899eff700a03.png",
"image_medium": "https://s.gr-assets.com/assets/nophoto/book/111x148-bcc042a9c91a29c1d680899eff700a03.png",
"isbn": "",
"language_code": "",
"original_publication_year": 2003,
"original_series": "Cirque Du Freak",
"original_title": "Killers of the Dawn (Cirque Du Freak, #9)",
"ratings_count": 18194,
"title": "Killers of the Dawn (Cirque Du Freak, #9)"
}
},
{
"_index": "good-books-ds",
"_type": "good-books-ds",
"_id": "5683",
"_score": 1,
"_source": {
"authors": "Laura Joffe Numeroff, Felicia Bond",
"average_rating": 4.16,
"average_rating_rounded": 4,
"books_count": 13,
"id": 5683,
"image": "https://s.gr-assets.com/assets/nophoto/book/111x148-bcc042a9c91a29c1d680899eff700a03.png",
"image_medium": "https://s.gr-assets.com/assets/nophoto/book/111x148-bcc042a9c91a29c1d680899eff700a03.png",
"isbn": "60278684",
"language_code": "",
"original_publication_year": 2000,
"original_series": "",
"original_title": "If You Take a Mouse to the Movies",
"ratings_count": 17938,
"title": "If You Take a Mouse to the Movies"
}
},
{
"_index": "good-books-ds",
"_type": "good-books-ds",
"_id": "5685",
"_score": 1,
"_source": {
"authors": "Orson Scott Card, James Cameron",
"average_rating": 4.06,
"average_rating_rounded": 4,
"books_count": 15,
"id": 5685,
"image": "https://images.gr-assets.com/books/1225165505l/40289.jpg",
"image_medium": "https://images.gr-assets.com/books/1225165505m/40289.jpg",
"isbn": "99690608",
"language_code": "eng",
"original_publication_year": 1989,
"original_series": "",
"original_title": "The Abyss",
"ratings_count": 16318,
"title": "The Abyss"
}
},
{
"_index": "good-books-ds",
"_type": "good-books-ds",
"_id": "5687",
"_score": 1,
"_source": {
"authors": "Katarina Bivald, Alice Menzies",
"average_rating": 3.56,
"average_rating_rounded": 4,
"books_count": 63,
"id": 5687,
"image": "https://images.gr-assets.com/books/1452107441l/25573977.jpg",
"image_medium": "https://images.gr-assets.com/books/1452107441m/25573977.jpg",
"isbn": "149262344X",
"language_code": "eng",
"original_publication_year": 2013,
"original_series": "",
"original_title": "Läsarna i Broken Wheel rekommenderar",
"ratings_count": 14571,
"title": "The Readers of Broken Wheel Recommend"
}
}
]
}
}
Значение, полученное как _scroll_id
, может быть передано в API прокрутки для получения следующего набора результатов и т. Д., Пока число обращений не станет равным нулю.
Примечание
Если в вашем кластере много данных, не рекомендуется запускать эту логику для получения всех результатов при каждом изменении запроса. Вы можете добавить условие, чтобы ограничить число полученных результатов или сохранить текущий запрос в состоянии и получать все результаты только при необходимости.
Вот пример того, как вы можете реализовать это с помощью ReactiveList
. В этом примере я извлекаю результаты каждый раз, когда изменяется запрос, но вы можете изменить его для условного извлечения результатов:
В вашей render
функции:
<ReactiveList
...
size={10}
onQueryChange={this.handleQueryChange}
/>
Вот как может выглядеть функция handleQueryChange
. Это даст вам все результаты для текущего запроса:
handleQueryChange = async (prev, next) => {
// avoid fetching the results for match_all query since dataset is large
if (next && !next.query.match_all) {
console.log('Fetching all results for query:', next);
// modify the query size here if needed (currently it is 10)
// initial url to obtain scroll id is different
const initialResults = await this.fetchResults(next, url);
// keep scrolling till hits are present
// NOTE: careful if you've a lot of results,
// in that case you might want to add a condition to limit calls to scroll API
const scrollResults = await this.fetchScrollResults({
scroll: "1m",
scroll_id: initialResults._scroll_id
});
// combine the two to get all results
// concat hits from initialResults with hits from scrollResults
const allResults = initialResults.hits.hits.concat(scrollResults);
console.log(`${allResults.length} results found:`, allResults);
}
};
Он использует две функции для получения результатов сначала и позже с scroll_id
. Конечные точки для обоих отличаются, что вы можете найти в демоверсии 1075 *. Вот как выглядит первый fetchResults
:
fetchResults = (query, api) => {
return fetch(api, {
method: "POST",
headers: {
"content-type": "application/json",
Authorization: `Basic ${btoa(credentials)}`
},
body: JSON.stringify(query)
})
.then(res => res.json())
.catch(err => console.error(err));
};
fetchScrollResults
будет использовать API прокрутки для извлечения результатов до тех пор, пока полученные хиты не станут равны 0.
fetchScrollResults = async query => {
const res = await this.fetchResults(query, scrollUrl);
const { hits } = res.hits;
if (hits.length) {
return [
...hits,
...(await this.fetchScrollResults({
scroll: "1m",
scroll_id: res._scroll_id
}))
];
}
return [];
};
Проверьте демо , результаты появятся в консоли.