Skip to content

Commit 670b445

Browse files
Adding readMany() support for findAllByIds() to improve performance. (Azure#43759)
* Adding readMany() support for findAllByIds() to improve performance. * Updating the changelog * Update sdk/spring/azure-spring-data-cosmos/CHANGELOG.md Co-authored-by: Kushagra Thapar <[email protected]> --------- Co-authored-by: Kushagra Thapar <[email protected]>
1 parent 792e9e2 commit 670b445

File tree

3 files changed

+105
-6
lines changed

3 files changed

+105
-6
lines changed

sdk/spring/azure-spring-data-cosmos/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
### 5.21.0-beta.1 (Unreleased)
44

55
#### Features Added
6+
* Added `readMany()` API support to `findAllByIds()` - See [PR 43759](https://github.com/Azure/azure-sdk-for-java/pull/43759).
67

78
#### Breaking Changes
89

sdk/spring/azure-spring-data-cosmos/src/main/java/com/azure/spring/data/cosmos/core/CosmosTemplate.java

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@
1212
import com.azure.cosmos.models.CosmosContainerProperties;
1313
import com.azure.cosmos.models.CosmosContainerResponse;
1414
import com.azure.cosmos.models.CosmosDatabaseResponse;
15+
import com.azure.cosmos.models.CosmosItemIdentity;
1516
import com.azure.cosmos.models.CosmosItemOperation;
1617
import com.azure.cosmos.models.CosmosItemRequestOptions;
1718
import com.azure.cosmos.models.CosmosItemResponse;
1819
import com.azure.cosmos.models.CosmosPatchItemRequestOptions;
1920
import com.azure.cosmos.models.CosmosPatchOperations;
2021
import com.azure.cosmos.models.CosmosQueryRequestOptions;
22+
import com.azure.cosmos.models.CosmosReadManyRequestOptions;
2123
import com.azure.cosmos.models.FeedResponse;
2224
import com.azure.cosmos.models.PartitionKey;
2325
import com.azure.cosmos.models.PartitionKeyDefinition;
@@ -856,13 +858,40 @@ public <T, ID> Iterable<T> findByIds(Iterable<ID> ids, Class<T> domainType, Stri
856858
Assert.notNull(ids, "Id list should not be null");
857859
Assert.notNull(domainType, "domainType should not be null.");
858860
Assert.hasText(containerName, "container should not be null, empty or only whitespaces");
859-
final List<Object> idList = new ArrayList<>();
860-
for (ID id : ids) {
861-
idList.add(CosmosUtils.getStringIDValue(id));
861+
862+
CosmosEntityInformation<?, ?> cosmosEntityInformation = CosmosEntityInformation.getInstance(domainType);
863+
String containerPartitionKey = cosmosEntityInformation.getPartitionKeyFieldName();
864+
if ("id".equals(containerPartitionKey) && ids.iterator().next() != null) {
865+
List<CosmosItemIdentity> idList = new ArrayList<>();
866+
for (ID id : ids) {
867+
idList.add(new CosmosItemIdentity(new PartitionKey(id), String.valueOf(id)));
868+
}
869+
870+
final CosmosReadManyRequestOptions cosmosReadManyRequestOptions = new CosmosReadManyRequestOptions();
871+
containerName = getContainerNameOverride(containerName);
872+
cosmosReadManyRequestOptions.setQueryMetricsEnabled(this.queryMetricsEnabled);
873+
cosmosReadManyRequestOptions.setIndexMetricsEnabled(this.indexMetricsEnabled);
874+
cosmosReadManyRequestOptions.setResponseContinuationTokenLimitInKb(this.responseContinuationTokenLimitInKb);
875+
876+
return this.getCosmosAsyncClient()
877+
.getDatabase(this.getDatabaseName())
878+
.getContainer(containerName)
879+
.readMany(idList, cosmosReadManyRequestOptions, domainType)
880+
.publishOn(CosmosSchedulers.SPRING_DATA_COSMOS_PARALLEL)
881+
.onErrorResume(throwable ->
882+
CosmosExceptionUtils.exceptionHandler("Failed to find items", throwable,
883+
this.responseDiagnosticsProcessor))
884+
.block().getResults();
885+
} else {
886+
final List<Object> idList = new ArrayList<>();
887+
for (ID id : ids) {
888+
idList.add(CosmosUtils.getStringIDValue(id));
889+
}
890+
final CosmosQuery query = new CosmosQuery(Criteria.getInstance(CriteriaType.IN, "id",
891+
Collections.singletonList(idList), Part.IgnoreCaseType.NEVER));
892+
return find(query, domainType, containerName);
862893
}
863-
final CosmosQuery query = new CosmosQuery(Criteria.getInstance(CriteriaType.IN, "id",
864-
Collections.singletonList(idList), Part.IgnoreCaseType.NEVER));
865-
return find(query, domainType, containerName);
894+
866895
}
867896

868897
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
package com.azure.spring.data.cosmos.repository.integration;
4+
5+
import com.azure.spring.data.cosmos.IntegrationTestCollectionManager;
6+
import com.azure.spring.data.cosmos.common.ResponseDiagnosticsTestUtils;
7+
import com.azure.spring.data.cosmos.common.TestUtils;
8+
import com.azure.spring.data.cosmos.config.CosmosConfig;
9+
import com.azure.spring.data.cosmos.core.CosmosTemplate;
10+
import com.azure.spring.data.cosmos.domain.Address;
11+
import com.azure.spring.data.cosmos.domain.BasicItem;
12+
import com.azure.spring.data.cosmos.repository.TestRepositoryConfig;
13+
import com.azure.spring.data.cosmos.repository.repository.BasicItemRepository;
14+
import org.assertj.core.util.Lists;
15+
import org.junit.Assert;
16+
import org.junit.Before;
17+
import org.junit.ClassRule;
18+
import org.junit.Test;
19+
import org.junit.runner.RunWith;
20+
import org.springframework.beans.factory.annotation.Autowired;
21+
import org.springframework.test.context.ContextConfiguration;
22+
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
23+
24+
import java.util.ArrayList;
25+
import java.util.Arrays;
26+
import java.util.Iterator;
27+
28+
import static com.azure.spring.data.cosmos.common.TestConstants.ID_1;
29+
import static com.azure.spring.data.cosmos.common.TestConstants.ID_2;
30+
31+
@RunWith(SpringJUnit4ClassRunner.class)
32+
@ContextConfiguration(classes = TestRepositoryConfig.class)
33+
public class BasicItemRepositoryIT {
34+
35+
@ClassRule
36+
public static final IntegrationTestCollectionManager collectionManager = new IntegrationTestCollectionManager();
37+
38+
@Autowired
39+
BasicItemRepository repository;
40+
41+
@Autowired
42+
CosmosConfig cosmosConfig;
43+
44+
@Autowired
45+
private CosmosTemplate template;
46+
47+
@Autowired
48+
private ResponseDiagnosticsTestUtils responseDiagnosticsTestUtils;
49+
50+
private static final BasicItem BASIC_ITEM_1 = new BasicItem(ID_1);
51+
52+
private static final BasicItem BASIC_ITEM_2 = new BasicItem(ID_2);
53+
54+
@Before
55+
public void setUp() {
56+
collectionManager.ensureContainersCreatedAndEmpty(template, Address.class);
57+
repository.saveAll(Lists.newArrayList(BASIC_ITEM_1, BASIC_ITEM_2));
58+
}
59+
60+
@Test
61+
public void testFindAllById() {
62+
final Iterable<BasicItem> allById =
63+
TestUtils.toList(this.repository.findAllById(Arrays.asList(BASIC_ITEM_1.getId(), BASIC_ITEM_2.getId())));
64+
Assert.assertTrue(((ArrayList) allById).size() == 2);
65+
Iterator<BasicItem> it = allById.iterator();
66+
Assert.assertEquals(BASIC_ITEM_1, it.next());
67+
Assert.assertEquals(BASIC_ITEM_2, it.next());
68+
}
69+
}

0 commit comments

Comments
 (0)