diff --git a/api/pom.xml b/api/pom.xml
index f77e271d2..7ff47245c 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -58,6 +58,11 @@
argon2-jvm
2.4
+
+ org.apache.httpcomponents
+ fluent-hc
+ 4.5.6
+
org.vivoweb
vitro-dependencies
diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/searchengine/elasticsearch/ESAdder.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/searchengine/elasticsearch/ESAdder.java
new file mode 100644
index 000000000..860e02b8d
--- /dev/null
+++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/searchengine/elasticsearch/ESAdder.java
@@ -0,0 +1,92 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.searchengine.elasticsearch;
+
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.client.fluent.Request;
+import org.apache.http.client.fluent.Response;
+import org.apache.http.entity.ContentType;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngineException;
+import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchInputDocument;
+import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchInputField;
+
+/**
+ * The nuts and bolts of adding a document to the Elasticsearch index
+ */
+public class ESAdder {
+ private static final Log log = LogFactory.getLog(ESAdder.class);
+
+ private final String baseUrl;
+
+ public ESAdder(String baseUrl) {
+ this.baseUrl = baseUrl;
+ }
+
+ public void add(Collection docs)
+ throws SearchEngineException {
+ for (SearchInputDocument doc : docs) {
+ addDocument(doc);
+ }
+ }
+
+ private void addDocument(SearchInputDocument doc)
+ throws SearchEngineException {
+ try {
+ Map> map = convertDocToMap(doc);
+ String json = new ObjectMapper().writeValueAsString(map);
+ log.debug("Adding document for '" + doc.getField("DocId") + "': "
+ + json);
+
+ putToElastic(json, (String) doc.getField("DocId").getFirstValue());
+ } catch (Exception e) {
+ throw new SearchEngineException("Failed to convert to JSON", e);
+ }
+ }
+
+ /**
+ * Some field values are collections. Add the members of the collection
+ * instead.
+ */
+ private Map> convertDocToMap(SearchInputDocument doc) {
+ Map> map = new HashMap<>();
+ for (SearchInputField field : doc.getFieldMap().values()) {
+ ArrayList