apoc.mongodb.MongoDBColl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of apoc Show documentation
Show all versions of apoc Show documentation
A collection of useful Neo4j Procedures
package apoc.mongodb;
import apoc.util.Util;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.MongoCommandException;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import org.apache.commons.lang3.StringUtils;
import org.bson.BsonDouble;
import org.bson.BsonInt32;
import org.bson.BsonInt64;
import org.bson.BsonNumber;
import org.bson.BsonRegularExpression;
import org.bson.BsonTimestamp;
import org.bson.Document;
import org.bson.types.Binary;
import org.bson.types.Code;
import org.bson.types.MaxKey;
import org.bson.types.MinKey;
import org.bson.types.ObjectId;
import org.bson.types.Symbol;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import static java.lang.String.format;
/**
* @author mh
* @since 30.06.16
*/
class MongoDBColl implements MongoDBUtils.Coll {
private static final ObjectMapper jsonMapper = new ObjectMapper().enable(DeserializationFeature.USE_LONG_FOR_INTS);
public static final String ID = "_id";
private final MongoCollection collection;
private final MongoClient mongoClient;
private boolean compatibleValues = false;
private boolean doorStop = false;
private final MongoDatabase database;
private boolean extractReferences = false;
private boolean objectIdAsMap = true;
// visible for testing
public static final String ERROR_MESSAGE = "The connection string must have %s name";
private MongoDBColl(String url, String db, String coll) {
MongoClientURI connectionString = new MongoClientURI(url);
mongoClient = new MongoClient(connectionString);
database = mongoClient.getDatabase(db);
collection = database.getCollection(coll);
}
/**
*
* @param url
* @param db
* @param coll
* @param compatibleValues if true we convert the document to JSON and than back to a Map
*/
public MongoDBColl(String url, String db, String coll, boolean compatibleValues,
boolean extractReferences, boolean objectIdAsMap) {
this(url, db, coll);
getConfigs(compatibleValues, extractReferences, objectIdAsMap);
}
/**
*
* @param uri the string Uri to convert in connectionString
* @see MongoClientURI
* @param conf the configuration
* @see MongoDbConfig
*/
public MongoDBColl(String uri, MongoDbConfig conf) {
MongoClientURI connectionString = new MongoClientURI(uri);
if (connectionString.getDatabase() == null) {
throw new RuntimeException(format(ERROR_MESSAGE, "db"));
}
final String collectionName;
final String confCollection = conf.getCollection();
if (StringUtils.isNotBlank(confCollection)) {
collectionName = confCollection;
} else {
final String collectionFromUri = connectionString.getCollection();
if (collectionFromUri == null) {
throw new RuntimeException(format(ERROR_MESSAGE, "collection"));
}
collectionName = collectionFromUri;
}
mongoClient = new MongoClient(connectionString);
database = mongoClient.getDatabase(connectionString.getDatabase());
try {
// check if correctly authenticated
database.runCommand(new Document("listCollections", 1));
} catch (MongoCommandException e) {
mongoClient.close();
throw new RuntimeException(e);
}
this.collection = database.getCollection(collectionName);
// with new procedure we return always Neo4j values
getConfigs(true, conf.isExtractReferences(), conf.isObjectIdAsMap());
}
private void getConfigs(boolean compatibleValues, boolean extractReferences, boolean objectIdAsMap) {
this.compatibleValues = compatibleValues;
this.extractReferences = extractReferences;
this.objectIdAsMap = objectIdAsMap;
}
@Override
public void close() {
if (doorStop) return;
mongoClient.close();
}
/**
* It translates a MongoDB document into a Map where the "_id" field is not an ObjectId
* but a simple String representation of it
*
* @param document
*
* @return
*/
private Map documentToPackableMap(Map document) {
return (Map) convertAndExtract(document);
}
public Object convertAndExtract(Object data) {
if (data == null) {
return null;
}
if (data instanceof Map) {
Map map = (Map) data;
return map.entrySet().stream()
.map(e -> {
Object value;
if (ID.equals(e.getKey())) { // avoid circular conversions
if (compatibleValues && objectIdAsMap) {
try {
value = jsonMapper.readValue(jsonMapper.writeValueAsBytes(e.getValue()), Map.class);
} catch (Exception exc) {
throw new RuntimeException("Cannot convert document to json and back to Map " + exc.getMessage());
}
} else {
value = e.getValue().toString();
}
} else {
value = convertAndExtract(e.getValue());
}
return new AbstractMap.SimpleEntry(e.getKey(), value);
})
.collect(HashMap::new, (m, e)-> m.put(e.getKey(), e.getValue()), HashMap::putAll); // please look at https://bugs.openjdk.java.net/browse/JDK-8148463
}
if (data instanceof Collection) {
Collection