# Recommendation to use search after instead of scrolling

**URL:** <https://discuss.elastic.co/t/recommendation-to-use-search-after-instead-of-scrolling/268293>\
**Category:** Elasticsearch\
**Created:** [March 25, 2021, 6:31am UTC](https://discuss.elastic.co/t/recommendation-to-use-search-after-instead-of-scrolling/268293 "2021-03-25T06:31:43Z")\
**Posts on this page:** 1\
**Showing post:** 5

<div class="post-metadata">

**Author:** ![prelator](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/prelator/32/82242_2.png) [@prelator](https://discuss.elastic.co/u/prelator)\
**Post date:** [March 25, 2021, 9:58am UTC](https://discuss.elastic.co/t/recommendation-to-use-search-after-instead-of-scrolling/268293/5 "2021-03-25T09:58:20Z")

</div>

> [@dadoonet](#):
>
> Or use markdown style like:

sorry - fixed.

> [@dadoonet](#):
>
> That's a huge difference indeed.  
> I'd may be try to decrease the `size` for `search_after` . But for your use case anyway, I'd use the scroll API as your goal is to extract everything.
> 
> Pinging @jimczi as he might know what is happening.

i have testet it with different sizes.

our test with different sizes:  
(first param = document count, second param = size)

code:

```auto
    @ParameterizedTest
    @CsvSource({
            "17, 3",
            "10, 2",
            "0, 1",
            "1, 1",
            "13, 2",
            "10, 3"
            "100001, 50",
            "100001, 100",
            "100001, 500",
            "100001, 1000",
            "100001, 5000",
            "100001, 20000",
    })
    void newTestScrollClosing(int givenTestObjects, int chunksize) {
        client.createIndexByFilename(indexName);

        List<TestObject> testObjectList = IntStream.range(0, givenTestObjects).boxed()
                .map(i -> new TestObject(UUID.randomUUID().toString(), i))
                .collect(Collectors.toList());
        client.insertBulk(testObjectList, WriteRequest.RefreshPolicy.IMMEDIATE);

        List<TestObject> results = new ArrayList<>();

        for (ElasticChunkResult<TestObject> result = client.newStartIterate(chunksize); !result
                .isEmpty(); result = client.newNextChunk(result)) {
            results.addAll(result.getObjects());
        }

        assertThat(results).hasSize(givenTestObjects);
        assertThat(results).containsExactlyInAnyOrderElementsOf(testObjectList);
    }

```

results with search\_after:

![image](https://us1.discourse-cdn.com/elastic/original/3X/c/b/cb12042ff736800ef21b3a4042e9f36db7a3e9d5.png)

results with \_scroll:

![image](https://us1.discourse-cdn.com/elastic/original/3X/2/b/2bf056b2e26bdfab598e6dc2ce4827381edb0a90.png)

Java Code for query and search\_after:

```auto
 public ElasticChunkResult<T> newStartIterate(int viewSize) {
        SearchRequest searchRequest = new SearchRequest(indexname);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.size(viewSize);
        searchSourceBuilder.sort(SortBuilders.fieldSort("_id").order(SortOrder.ASC));
        searchRequest.source(searchSourceBuilder);

        SearchResponse response;
        try {
            response = client.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException("Fehler beim SearchRequest", e);
        }

        List<T> hits = convertHits(response);

        return new ElasticChunkResult<>(determineLastObject(response, hits), hits, viewSize);
    }

    public ElasticChunkResult<T> newNextChunk(ElasticChunkResult elasticChunkResult) {

        if (elasticChunkResult.isEmpty()) {
            return elasticChunkResult;
        }

        SearchRequest searchRequest = new SearchRequest(indexname);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.size(elasticChunkResult.getChunkSize());
        searchSourceBuilder.sort(SortBuilders.fieldSort("_id").order(SortOrder.ASC));
        searchSourceBuilder.searchAfter(new Object[] { elasticChunkResult.getLastObject() });
        searchRequest.source(searchSourceBuilder);

        SearchResponse response;
        try {
            response = client.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException("Fehler beim SearchRequest", e);
        }

        List<T> hits = convertHits(response);

        return new ElasticChunkResult<>(determineLastObject(response, hits), hits, elasticChunkResult.getChunkSize());
    }

    private Object determineLastObject(SearchResponse response, List<T> hits) {
        Object lastObject = null;

        if (!hits.isEmpty()) {
            lastObject = response.getHits().getAt(response.getHits().getHits().length - 1).getId();
        }
        return lastObject;
    }

```

---

_[View the full topic](https://discuss.elastic.co/t/recommendation-to-use-search-after-instead-of-scrolling/268293)._
