package org.xbib.elasticsearch.plugin.bundle.test.index.mapper.reference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.lucene.index.IndexableField; import org.apache.lucene.util.SuppressForbidden; import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest; import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.support.WriteRequest; import org.elasticsearch.cluster.metadata.MappingMetaData; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.index.IndexService; import org.elasticsearch.index.mapper.DocumentMapper; import org.elasticsearch.index.mapper.ParseContext; import org.elasticsearch.index.mapper.SourceToParse; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.search.SearchHit; import org.elasticsearch.test.ESSingleNodeTestCase; import org.junit.After; import org.junit.Before; import org.xbib.elasticsearch.plugin.bundle.BundlePlugin; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.Collections; import static org.elasticsearch.common.io.Streams.copyToString; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.index.query.QueryBuilders.matchPhraseQuery; /** * Reference mapping tests. */ public class ReferenceMappingTests extends ESSingleNodeTestCase { private static final Logger logger = LogManager.getLogger(ReferenceMappingTests.class.getName()); /** The plugin classes that should be added to the node. */ @Override protected Collection<Class<? extends Plugin>> getPlugins() { return Collections.singletonList(BundlePlugin.class); } @Before public void setupReferences() throws Exception { try { client().admin().indices().prepareDelete("test").execute().actionGet(); } catch (Exception e) { logger.warn("unable to delete 'test' index"); } client().prepareIndex("test", "test", "1234") .setSource(jsonBuilder().startObject().array("myfield", "a","b","c").endObject()) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) .execute().actionGet(); try { client().admin().indices().prepareDelete("authorities").execute().actionGet(); } catch (Exception e) { logger.warn("unable to delete 'authorities' index"); } client().prepareIndex("authorities", "persons", "1") .setSource(jsonBuilder().startObject().field("author", "John Doe").endObject()) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) .execute().actionGet(); } @After public void destroyReferences() { try { client().admin().indices().prepareDelete("test").execute().actionGet(); } catch (Exception e) { logger.warn("unable to delete 'test' index"); } try { client().admin().indices().prepareDelete("authorities").execute().actionGet(); } catch (Exception e) { logger.warn("unable to delete 'authorities' index"); } } public void testRefMappings() throws Exception { IndexService indexService = createIndex("some_index", Settings.EMPTY, "some_type", getMapping("ref-mapping.json")); DocumentMapper docMapper = indexService.mapperService().documentMapper("some_type"); BytesReference json = BytesReference.bytes(jsonBuilder().startObject() .field("someField", "1234") .endObject()); SourceToParse sourceToParse = SourceToParse.source("some_index", "some_type", "1", json, XContentType.JSON); ParseContext.Document doc = docMapper.parse(sourceToParse).rootDoc(); assertNotNull(doc); for (IndexableField field : doc.getFields()) { logger.info("testRefMappings {} = {}", field.name(), field.stringValue()); } assertNotNull(docMapper.mappers().smartNameFieldMapper("someField")); assertEquals("1234", doc.getFields("someField")[0].stringValue()); assertEquals(3, doc.getFields("ref").length); assertEquals("a", doc.getFields("ref")[0].stringValue()); assertEquals("b", doc.getFields("ref")[1].stringValue()); assertEquals("c", doc.getFields("ref")[2].stringValue()); } public void testRefInDoc() throws Exception { IndexService indexService = createIndex("docs", Settings.EMPTY, "docs", getMapping("ref-mapping-authorities.json")); DocumentMapper docMapper = indexService.mapperService().documentMapper("docs"); BytesReference json = BytesReference.bytes(jsonBuilder().startObject() .field("title", "A title") .field("dc.creator", "A creator") .field("bib.contributor", "A contributor") .field("authorID", "1") .endObject()); SourceToParse sourceToParse = SourceToParse.source("docs", "docs", "1", json, XContentType.JSON); ParseContext.Document doc = docMapper.parse(sourceToParse).rootDoc(); for (IndexableField field : doc.getFields()) { logger.info("testRefInDoc {} = {}", field.name(), field.stringValue()); } assertEquals(2, doc.getFields("dc.creator").length); assertEquals("A creator", doc.getFields("dc.creator")[0].stringValue()); assertEquals("John Doe", doc.getFields("dc.creator")[1].stringValue()); assertEquals(2, doc.getFields("bib.contributor").length); assertEquals("A contributor", doc.getFields("bib.contributor")[0].stringValue()); assertEquals("John Doe", doc.getFields("bib.contributor")[1].stringValue()); } public void testRefFromID() throws Exception { IndexService indexService = createIndex("docs", Settings.EMPTY, "docs", getMapping("ref-mapping-from-id.json")); DocumentMapper docMapper = indexService.mapperService().documentMapper("docs"); BytesReference json = BytesReference.bytes(jsonBuilder().startObject() .field("title", "A title") .field("authorID", "1") .endObject()); SourceToParse sourceToParse = SourceToParse.source("docs", "docs", "1", json, XContentType.JSON); ParseContext.Document doc = docMapper.parse(sourceToParse).rootDoc(); assertEquals(1, doc.getFields("ref").length, 1); assertEquals("John Doe", doc.getFields("ref")[0].stringValue()); } public void testSearch() throws Exception { try { client().admin().indices().prepareDelete("books").execute().actionGet(); } catch (Exception e) { logger.warn("unable to delete index 'books'"); } client().admin().indices().prepareCreate("books") .addMapping("test", copyToStringFromClasspath("ref-mapping-books-test.json"), XContentType.JSON) .execute().actionGet(); client().prepareIndex("books", "test", "1") .setSource(copyToStringFromClasspath("ref-doc-book.json"), XContentType.JSON) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).execute().actionGet(); // get mappings GetMappingsResponse getMappingsResponse= client().admin().indices().getMappings(new GetMappingsRequest() .indices("books") .types("test")) .actionGet(); MappingMetaData md = getMappingsResponse.getMappings().get("books").get("test"); logger.info("mappings={}", md.getSourceAsMap()); // search in field 1, unreferenced value QueryBuilder queryBuilder = matchPhraseQuery("dc.creator", "A creator"); SearchResponse searchResponse = client().prepareSearch("books") .setQuery(queryBuilder).execute().actionGet(); logger.info("unref hits = {}", searchResponse.getHits().getTotalHits()); for (SearchHit hit : searchResponse.getHits().getHits()) { logger.info("{}", hit.getSourceAsMap()); } assertEquals(1, searchResponse.getHits().getTotalHits()); // search in field 1, referenced value queryBuilder = matchPhraseQuery("dc.creator", "John Doe"); searchResponse = client().prepareSearch("books") .setQuery(queryBuilder).execute().actionGet(); logger.info("ref hits = {}", searchResponse.getHits().getTotalHits()); for (SearchHit hit : searchResponse.getHits().getHits()) { logger.info("{}", hit.getSourceAsMap()); } assertEquals(1, searchResponse.getHits().getTotalHits()); // search in field 2, unreferenced value queryBuilder = matchPhraseQuery("bib.contributor", "A contributor"); searchResponse = client().prepareSearch("books") .setQuery(queryBuilder).execute().actionGet(); logger.info("field 2 unref hits = {}", searchResponse.getHits().getTotalHits()); for (SearchHit hit : searchResponse.getHits().getHits()) { logger.info("{}", hit.getSourceAsMap()); } assertEquals(1, searchResponse.getHits().getTotalHits()); // search in field 2, referenced value queryBuilder = matchPhraseQuery("bib.contributor", "John Doe"); searchResponse = client().prepareSearch("books") .setQuery(queryBuilder).execute().actionGet(); logger.info("field 2 ref hits = {}", searchResponse.getHits().getTotalHits()); for (SearchHit hit : searchResponse.getHits().getHits()) { logger.info("{}", hit.getSourceAsMap()); } assertEquals(1, searchResponse.getHits().getTotalHits()); } @SuppressForbidden(reason = "accessing local resources from classpath") private String copyToStringFromClasspath(String path) throws Exception { return copyToString(new InputStreamReader(getClass().getResource(path).openStream(), StandardCharsets.UTF_8)); } private XContentBuilder getMapping(String path) throws Exception { return XContentFactory.jsonBuilder().map(XContentHelper.convertToMap(JsonXContent.jsonXContent, getClass().getResourceAsStream(path), true)); } }