Skip to content

Commit eb979d1

Browse files
authored
Merge pull request #482 from marklogic/feature/metadata-values
MLE-21267 Can now configure metadata values and document properties
2 parents e491788 + 743f61d commit eb979d1

File tree

4 files changed

+71
-1
lines changed

4 files changed

+71
-1
lines changed

marklogic-spark-api/src/main/java/com/marklogic/spark/Options.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,17 @@ public abstract class Options {
118118
public static final String WRITE_COLLECTIONS = "spark.marklogic.write.collections";
119119
public static final String WRITE_PERMISSIONS = "spark.marklogic.write.permissions";
120120
public static final String WRITE_JSON_ROOT_NAME = "spark.marklogic.write.jsonRootName";
121+
122+
/**
123+
* @since 2.6.0
124+
*/
125+
public static final String WRITE_METADATA_VALUES_PREFIX = "spark.marklogic.write.metadataValues.";
126+
127+
/**
128+
* @since 2.6.0
129+
*/
130+
public static final String WRITE_DOCUMENT_PROPERTIES_PREFIX = "spark.marklogic.write.documentProperties.";
131+
121132
public static final String WRITE_TEMPORAL_COLLECTION = "spark.marklogic.write.temporalCollection";
122133
public static final String WRITE_URI_PREFIX = "spark.marklogic.write.uriPrefix";
123134
public static final String WRITE_URI_REPLACE = "spark.marklogic.write.uriReplace";

marklogic-spark-connector/src/main/java/com/marklogic/spark/writer/DocBuilderFactory.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ DocBuilderFactory withPermissions(String permissionsString) {
4242
return this;
4343
}
4444

45+
DocBuilderFactory withMetadataValue(String key, String value) {
46+
metadata.withMetadataValue(key, value);
47+
return this;
48+
}
49+
50+
DocBuilderFactory withDocumentProperty(String name, Object value) {
51+
metadata.withProperty(name, value);
52+
return this;
53+
}
54+
4555
DocBuilderFactory withUriMaker(DocBuilder.UriMaker uriMaker) {
4656
this.uriMaker = uriMaker;
4757
return this;

marklogic-spark-connector/src/main/java/com/marklogic/spark/writer/WriteContext.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.List;
2323
import java.util.Map;
2424
import java.util.Optional;
25+
import java.util.function.BiConsumer;
2526
import java.util.stream.Stream;
2627

2728
public class WriteContext extends ContextSupport {
@@ -144,9 +145,27 @@ DocBuilder newDocBuilder() {
144145
configureStandardUriMaker(factory);
145146
}
146147

148+
forEachOptionStartingWith(Options.WRITE_METADATA_VALUES_PREFIX, factory::withMetadataValue);
149+
forEachOptionStartingWith(Options.WRITE_DOCUMENT_PROPERTIES_PREFIX, factory::withDocumentProperty);
150+
147151
return factory.newDocBuilder();
148152
}
149153

154+
/**
155+
* Convenience for finding and processing dynamic options that start with a certain prefix.
156+
*
157+
* @param prefix
158+
* @param consumer processes the name (the option minus the prefix) and the option value
159+
*/
160+
private void forEachOptionStartingWith(final String prefix, BiConsumer<String, String> consumer) {
161+
getProperties().entrySet().stream()
162+
.filter(entry -> entry.getKey().startsWith(prefix))
163+
.forEach(entry -> {
164+
String name = entry.getKey().substring(prefix.length());
165+
consumer.accept(name, entry.getValue());
166+
});
167+
}
168+
150169
public Format getDocumentFormat() {
151170
if (hasOption(Options.WRITE_DOCUMENT_TYPE)) {
152171
String value = getStringOption(Options.WRITE_DOCUMENT_TYPE);

tests/src/test/java/com/marklogic/spark/writer/WriteRowsTest.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package com.marklogic.spark.writer;
55

66
import com.fasterxml.jackson.databind.JsonNode;
7+
import com.marklogic.client.io.DocumentMetadataHandle;
78
import com.marklogic.junit5.PermissionsTester;
89
import com.marklogic.spark.ConnectorException;
910
import com.marklogic.spark.Options;
@@ -139,6 +140,34 @@ void testWithCustomConfig() {
139140
assertTrue(uri.endsWith(".txt"));
140141
}
141142

143+
@Test
144+
void metadataValues() {
145+
newWriter()
146+
.option(Options.WRITE_METADATA_VALUES_PREFIX + "color", "red")
147+
.option(Options.WRITE_METADATA_VALUES_PREFIX + "size", "medium")
148+
.save();
149+
150+
String firstUri = verifyTwoHundredDocsWereWritten();
151+
DocumentMetadataHandle.DocumentMetadataValues values = readMetadata(firstUri).getMetadataValues();
152+
assertEquals(2, values.size());
153+
assertEquals("red", values.get("color"));
154+
assertEquals("medium", values.get("size"));
155+
}
156+
157+
@Test
158+
void documentProperties() {
159+
newWriter()
160+
.option(Options.WRITE_DOCUMENT_PROPERTIES_PREFIX + "color", "red")
161+
.option(Options.WRITE_DOCUMENT_PROPERTIES_PREFIX + "size", "medium")
162+
.save();
163+
164+
String firstUri = verifyTwoHundredDocsWereWritten();
165+
DocumentMetadataHandle.DocumentProperties props = readMetadata(firstUri).getProperties();
166+
assertEquals(2, props.size());
167+
assertEquals("red", props.get("color"));
168+
assertEquals("medium", props.get("size"));
169+
}
170+
142171
@Test
143172
void invalidThreadCount() {
144173
DataFrameWriter writer = newWriter().option(Options.WRITE_THREAD_COUNT, 0);
@@ -257,7 +286,7 @@ private void verifyFailureIsDueToLackOfPermission(SparkException ex) {
257286
verifyNoDocsWereWritten();
258287
}
259288

260-
private void verifyTwoHundredDocsWereWritten() {
289+
private String verifyTwoHundredDocsWereWritten() {
261290
final int expectedCollectionSize = 200;
262291
String uri = getUrisInCollection(COLLECTION, expectedCollectionSize).get(0);
263292
assertTrue(uri.startsWith("/test/"), "URI should start with '/test/' due to uriPrefix option: " + uri);
@@ -270,6 +299,7 @@ private void verifyTwoHundredDocsWereWritten() {
270299
PermissionsTester perms = readDocumentPermissions(uri);
271300
perms.assertReadPermissionExists("spark-user-role");
272301
perms.assertUpdatePermissionExists("spark-user-role");
302+
return uri;
273303
}
274304

275305
private void verifyNoDocsWereWritten() {

0 commit comments

Comments
 (0)