Skip to content

Commit

Permalink
Feature/can merge statically typed documents (Azure#75)
Browse files Browse the repository at this point in the history
* async canMergeStaticallyTypedDocuments

* canMergeStaticallyTypedDocuments sync

* add canMergeStaticallyTypedDocuments.json

* Refactor to base. Change explicit null setting to leaving the fields out

* static working

* update all json in indexing tests

* fix merge conflict in json
  • Loading branch information
chenmliu authored and noelbundick committed Sep 13, 2019
1 parent 6a88e1a commit 53638e1
Show file tree
Hide file tree
Showing 14 changed files with 874 additions and 485 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@
import com.azure.search.data.common.jsonwrapper.jacksonwrapper.JacksonDeserializer;
import com.azure.search.data.customization.Document;
import com.azure.search.data.customization.IndexBatchBuilder;
import com.azure.search.data.customization.models.GeoPoint;
import com.azure.search.data.generated.models.DocumentIndexResult;
import com.azure.search.data.generated.models.IndexAction;
import com.azure.search.data.generated.models.IndexActionType;
import com.azure.search.data.generated.models.IndexBatch;
import com.azure.search.data.generated.models.IndexingResult;
import com.azure.search.data.models.Book;
import com.azure.search.data.models.Hotel;
import com.azure.search.data.models.HotelAddress;
import com.azure.search.data.models.HotelRoom;
import com.azure.search.service.models.DataType;
import com.azure.search.service.models.Field;
import com.azure.search.service.models.Index;
Expand Down Expand Up @@ -372,6 +375,147 @@ public void staticallyTypedDateTimesRoundTripAsUtc() throws Exception {
.verifyComplete();
}

@Override
public void canMergeStaticallyTypedDocuments() throws ParseException {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");

Hotel originalDoc = new Hotel()
.hotelId("1")
.hotelName("Secret Point Motel")
.description("The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.")
.descriptionFr("L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.")
.category("Boutique")
.tags(Arrays.asList("pool",
"air conditioning",
"concierge"))
.parkingIncluded(false)
.smokingAllowed(true)
.lastRenovationDate(dateFormat.parse("2010-06-27T00:00:00Z"))
.rating(4)
.location(GeoPoint.createWithDefaultCrs(40.760586, -73.975403))
.address(new HotelAddress()
.streetAddress("677 5th Ave")
.city("New York")
.stateProvince("NY")
.country("USA")
.postalCode("10022"))
.rooms(Arrays.asList(
new HotelRoom()
.description("Budget Room, 1 Queen Bed (Cityside)")
.descriptionFr("Chambre Économique, 1 grand lit (côté ville)")
.type("Budget Room")
.baseRate(9.69)
.bedOptions("1 Queen Bed")
.sleepsCount(2)
.smokingAllowed(true)
.tags(Arrays.asList("vcr/dvd")),
new HotelRoom()
.description("Budget Room, 1 King Bed (Mountain View)")
.descriptionFr("Chambre Économique, 1 très grand lit (Mountain View)")
.type("Budget Room")
.baseRate(8.09)
.bedOptions("1 King Bed")
.sleepsCount(2)
.smokingAllowed(true)
.tags(Arrays.asList("vcr/dvd",
"jacuzzi tub"))
));

// Update category, tags, parking included, rating, and rooms. Erase description, last renovation date, location and address.
Hotel updatedDoc = new Hotel()
.hotelId("1")
.hotelName("Secret Point Motel")
.description(null)
.category("Economy")
.tags(Arrays.asList("pool",
"air conditioning"))
.parkingIncluded(true)
.lastRenovationDate(null)
.rating(3)
.location(null)
.address(new HotelAddress())
.rooms(Arrays.asList(
new HotelRoom()
.description(null)
.type("Budget Room")
.baseRate(10.5)
.bedOptions("1 Queen Bed")
.sleepsCount(2)
.tags(Arrays.asList("vcr/dvd",
"balcony"))));

// Fields whose values get updated are updated, and whose values get erased remain the same.
Hotel expectedDoc = new Hotel()
.hotelId("1")
.hotelName("Secret Point Motel")
.description("The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.")
.descriptionFr("L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.")
.category("Economy")
.tags(Arrays.asList("pool",
"air conditioning"))
.parkingIncluded(true)
.smokingAllowed(true)
.lastRenovationDate(dateFormat.parse("2010-06-27T00:00:00Z"))
.rating(3)
.location(GeoPoint.createWithDefaultCrs(40.760586, -73.975403))
.address(new HotelAddress()
.streetAddress("677 5th Ave")
.city("New York")
.stateProvince("NY")
.country("USA")
.postalCode("10022"))
.rooms(Arrays.asList(
new HotelRoom()
.description(null)
.type("Budget Room")
.baseRate(10.5)
.bedOptions("1 Queen Bed")
.sleepsCount(2)
.tags(Arrays.asList("vcr/dvd",
"balcony"))));

JsonApi jsonApi = JsonWrapper.newInstance(JacksonDeserializer.class);
jsonApi.configureTimezone();

// Upload an original doc and merge it with an updated doc
IndexAction uploadOriginalDocAction = new IndexAction()
.actionType(IndexActionType.MERGE_OR_UPLOAD)
.additionalProperties(jsonApi.convertObjectToType(originalDoc, Map.class));
IndexAction replaceWithUpdatedDocAction = new IndexAction()
.actionType(IndexActionType.MERGE)
.additionalProperties(jsonApi.convertObjectToType(updatedDoc, Map.class));
IndexBatch batch1 = new IndexBatch()
.actions(Arrays.asList(uploadOriginalDocAction));
IndexBatch batch2 = new IndexBatch()
.actions(Arrays.asList(replaceWithUpdatedDocAction));

// Verify
StepVerifier.create(client.index(batch1))
.expectNextMatches(documentIndexResult -> documentIndexResult.results().size() == batch1.actions().size())
.verifyComplete();
StepVerifier.create(client.index(batch2))
.expectNextMatches(documentIndexResult -> documentIndexResult.results().size() == batch2.actions().size())
.verifyComplete();
StepVerifier.create(client.getDocument("1"))
.expectNextMatches(result -> result.as(Hotel.class).equals(expectedDoc))
.verifyComplete();

// Merge with the original doc
IndexAction replaceWithOriginalDocAction = new IndexAction()
.actionType(IndexActionType.MERGE)
.additionalProperties(jsonApi.convertObjectToType(originalDoc, Map.class));
IndexBatch batch3 = new IndexBatch()
.actions(Arrays.asList(replaceWithOriginalDocAction));

// Verify
StepVerifier.create(client.index(batch3))
.expectNextMatches(documentIndexResult -> documentIndexResult.results().size() == batch3.actions().size())
.verifyComplete();
StepVerifier.create(client.getDocument("1"))
.expectNextMatches(result -> result.as(Hotel.class).equals(originalDoc))
.verifyComplete();
}

@Override
protected void initializeClient() {
client = builderSetup().indexName(INDEX_NAME).buildAsyncClient();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@
import com.azure.search.data.common.jsonwrapper.api.JsonApi;
import com.azure.search.data.common.jsonwrapper.jacksonwrapper.JacksonDeserializer;
import com.azure.search.data.customization.Document;
import com.azure.search.data.customization.models.GeoPoint;
import com.azure.search.data.generated.models.IndexAction;
import com.azure.search.data.generated.models.IndexActionType;
import com.azure.search.data.generated.models.IndexBatch;
import com.azure.search.data.generated.models.IndexingResult;
import com.azure.search.data.models.Book;
import com.azure.search.data.models.Hotel;
import com.azure.search.data.models.HotelAddress;
import com.azure.search.data.models.HotelRoom;
import com.azure.search.service.models.DataType;
import com.azure.search.service.models.Field;
import com.azure.search.service.models.Index;
Expand All @@ -32,6 +35,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Date;
import java.util.stream.Collectors;


Expand Down Expand Up @@ -319,6 +323,134 @@ public void staticallyTypedDateTimesRoundTripAsUtc() throws Exception {
Assert.assertEquals(books.get(1).publishDate(), actualBook2.as(Book.class).publishDate());
}

@Override
public void canMergeStaticallyTypedDocuments() throws ParseException {
// Define commonly used values
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
String hotelId = "1";
String hotelName = "Secret Point Motel";
String description = "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.";
String descriptionFr = "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.";
GeoPoint location = GeoPoint.createWithDefaultCrs(40.760586, -73.975403);
HotelAddress address = new HotelAddress()
.streetAddress("677 5th Ave")
.city("New York")
.stateProvince("NY")
.country("USA")
.postalCode("10022");
Date lastRenovationDate = dateFormat.parse("2010-06-27T00:00:00Z");
List<HotelRoom> updatedRooms = Arrays.asList(
new HotelRoom()
.description(null)
.type("Budget Room")
.baseRate(10.5)
.bedOptions("1 Queen Bed")
.sleepsCount(2)
.tags(Arrays.asList("vcr/dvd",
"balcony"))
);
String updatedHotelCategory = "Economy";
List<String> updatedTags = Arrays.asList("pool",
"air conditioning");

// Define hotels
Hotel originalDoc = new Hotel()
.hotelId(hotelId)
.hotelName(hotelName)
.description(description)
.descriptionFr(descriptionFr)
.category("Boutique")
.tags(Arrays.asList("pool",
"air conditioning",
"concierge"))
.parkingIncluded(false)
.smokingAllowed(true)
.lastRenovationDate(lastRenovationDate)
.rating(4)
.location(location)
.address(address)
.rooms(Arrays.asList(
new HotelRoom()
.description("Budget Room, 1 Queen Bed (Cityside)")
.descriptionFr("Chambre Économique, 1 grand lit (côté ville)")
.type("Budget Room")
.baseRate(9.69)
.bedOptions("1 Queen Bed")
.sleepsCount(2)
.smokingAllowed(true)
.tags(Arrays.asList("vcr/dvd")),
new HotelRoom()
.description("Budget Room, 1 King Bed (Mountain View)")
.descriptionFr("Chambre Économique, 1 très grand lit (Mountain View)")
.type("Budget Room")
.baseRate(8.09)
.bedOptions("1 King Bed")
.sleepsCount(2)
.smokingAllowed(true)
.tags(Arrays.asList("vcr/dvd",
"jacuzzi tub"))
));
// Update category, tags, parking included, rating, and rooms. Erase description, last renovation date, location and address.
Hotel updatedDoc = new Hotel()
.hotelId(hotelId)
.hotelName(hotelName)
.description(null)
.category(updatedHotelCategory)
.tags(updatedTags)
.parkingIncluded(true)
.lastRenovationDate(null)
.rating(3)
.location(null)
.address(new HotelAddress())
.rooms(updatedRooms);
// Fields whose values get updated are updated, and whose values get erased remain the same.
Hotel expectedDoc = new Hotel()
.hotelId(hotelId)
.hotelName(hotelName)
.description(description)
.descriptionFr(descriptionFr)
.category(updatedHotelCategory)
.tags(updatedTags)
.parkingIncluded(true)
.smokingAllowed(true)
.lastRenovationDate(lastRenovationDate)
.rating(3)
.location(location)
.address(address)
.rooms(updatedRooms);

JsonApi jsonApi = JsonWrapper.newInstance(JacksonDeserializer.class);
jsonApi.configureTimezone();

// Upload an original doc and merge it with an updated doc
IndexAction uploadOriginalDocAction = new IndexAction()
.actionType(IndexActionType.MERGE_OR_UPLOAD)
.additionalProperties(jsonApi.convertObjectToType(originalDoc, Map.class));
IndexAction replaceWithUpdatedDocAction = new IndexAction()
.actionType(IndexActionType.MERGE)
.additionalProperties(jsonApi.convertObjectToType(updatedDoc, Map.class));
IndexBatch batch1 = new IndexBatch()
.actions(Arrays.asList(uploadOriginalDocAction));
IndexBatch batch2 = new IndexBatch()
.actions(Arrays.asList(replaceWithUpdatedDocAction));

// Verify
Assert.assertEquals(batch1.actions().size(), client.index(batch1).results().size());
Assert.assertEquals(batch2.actions().size(), client.index(batch2).results().size());
Assert.assertEquals(expectedDoc, client.getDocument(hotelId).as(Hotel.class));

// Merge with the original doc
IndexAction replaceWithOriginalDocAction = new IndexAction()
.actionType(IndexActionType.MERGE)
.additionalProperties(jsonApi.convertObjectToType(originalDoc, Map.class));
IndexBatch batch3 = new IndexBatch()
.actions(Arrays.asList(replaceWithOriginalDocAction));

// Verify
Assert.assertEquals(batch3.actions().size(), client.index(batch3).results().size());
Assert.assertEquals(originalDoc, client.getDocument(hotelId).as(Hotel.class));
}

@Override
protected void initializeClient() {
client = builderSetup().indexName(INDEX_NAME).buildClient();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ protected void assertFailedIndexResult(IndexingResult result, String key, int st
@Test
public abstract void staticallyTypedDateTimesRoundTripAsUtc() throws Exception;

@Test
public abstract void canMergeStaticallyTypedDocuments() throws ParseException;

protected abstract void initializeClient();

protected void assertIndexActionSucceeded(String key, IndexingResult result, int expectedStatusCode) {
Expand Down
Loading

0 comments on commit 53638e1

Please sign in to comment.