package com.yihu.hos.common.mongo; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.mongodb.MongoNamespace; import com.mongodb.client.*; import com.mongodb.client.model.*; import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.UpdateResult; import org.apache.commons.lang3.StringUtils; import org.bson.Document; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * MongoDBPro. Professional database CURD and Manager tool. * * @created Airhead 2016/2/17. */ public class MongoDBPro implements IMongoDBRunner, IMongoDBAdminer { private static final Map map = new HashMap(); private final MongoDBConfig config; public MongoDBPro() { if (MongoDBKit.config == null) { throw new RuntimeException("The main config is null, initialize MonogDBKit first"); } this.config = MongoDBKit.config; } public MongoDBPro(String configName) { this.config = MongoDBKit.getConfig(configName); if (this.config == null) { throw new IllegalArgumentException("Config not found by configName: " + configName); } } public static MongoDBPro use() { return use(MongoDBKit.config.name); } public static MongoDBPro use(String configName) { MongoDBPro result = map.get(configName); if (result == null) { result = new MongoDBPro(configName); map.put(configName, result); } return result; } public MongoDBPro db(String databaseName) { config.getDatabase(databaseName); return this; } @Override public long count(String collectionName) { return count(collectionName, null); } @Override public long count(String collectionName, String filter) { return count(collectionName, filter, null); } /** * @param collectionName * @param filter the query filter * @param options the options describing the count *

* { * limit: , * skip: , * hint: * } * @return */ @Override public long count(String collectionName, String filter, String options) { MongoCollection collection = getCollection(collectionName); Document filterDocument = new Document(); if (filter != null) { filterDocument = Document.parse(filter); } CountOptions countOptions = new CountOptions(); if (options != null) { ObjectMapper mapper = new ObjectMapper(); try { JsonNode rootNode = mapper.readValue(options, JsonNode.class); String hintString = rootNode.path("hint").toString(); if (!StringUtils.isEmpty(hintString)) { Document hint = Document.parse(hintString); countOptions.hint(hint); } else { countOptions.hint(new Document()); } countOptions.limit(rootNode.path("limit").asInt()); countOptions.skip(rootNode.path("skip").asInt()); } catch (IOException e) { e.printStackTrace(); } } return collection.count(filterDocument, countOptions); } @Override public List find(String collectionName) { return find(collectionName, null); } @Override public List find(String collectionName, String filter) { return find(collectionName, filter, null); } @Override public List find(String collectionName, String filter, String projection) { return find(collectionName, filter, projection, null); } @Override public List find(String collectionName, String filter, String projection, String options) { MongoCollection collection = getCollection(collectionName); Document filterDocument = new Document(); if (filter != null) { filterDocument = Document.parse(filter); } Document projectionDocument = new Document(); if (projection != null) { projectionDocument = Document.parse(projection); } FindIterable documents = collection.find(filterDocument).projection(projectionDocument); List list = new ArrayList<>(); try (MongoCursor cursor = documents.iterator()) { while (cursor.hasNext()) { Document doc = cursor.next(); list.add(doc.toJson()); } } return list; } // @Override // public List aggregate(String collectionName, List pipeline) { // return null; // } // @Override // public List mapReduce(String collectionName, String mapFunction, String reduceFunction) { // return null; // } @Override public void insertOne(String collectionName, String document) { MongoCollection collection = getCollection(collectionName); Document doc = Document.parse(document); collection.insertOne(doc); } @Override public void insertMany(String collectionName, List documents) { insertMany(collectionName, documents, null); } /** * @param collectionName * @param documents the documents to insert * @param options the options to apply to the operation * { * orderd: * } */ @Override public void insertMany(String collectionName, List documents, String options) { MongoCollection collection = getCollection(collectionName); List list = new ArrayList<>(); for (String document : documents) { Document doc = Document.parse(document); list.add(doc); } InsertManyOptions insertManyOptions = new InsertManyOptions(); if (options != null) { ObjectMapper mapper = new ObjectMapper(); try { JsonNode rootNode = mapper.readValue(options, JsonNode.class); insertManyOptions.ordered(rootNode.path("ordered").asBoolean()); } catch (IOException e) { e.printStackTrace(); } } collection.insertMany(list, insertManyOptions); } @Override public long deleteOne(String collectionName, String filter) { MongoCollection collection = getCollection(collectionName); Document filterDocument = Document.parse(filter); DeleteResult deleteResult = collection.deleteOne(filterDocument); return deleteResult.getDeletedCount(); } @Override public long deleteMany(String collectionName, String filter) { MongoCollection collection = getCollection(collectionName); Document filterDocument = Document.parse(filter); DeleteResult deleteResult = collection.deleteMany(filterDocument); return deleteResult.getDeletedCount(); } @Override public long replaceOne(String collectionName, String filter, String replacement) { return replaceOne(collectionName, filter, replacement, null); } /** * @param collectionName * @param filter the query filter to apply the the replace operation * @param replacement the replacement document * @param updateOptions the options to apply to the replace operation * { * upsert: * } * @return */ @Override public long replaceOne(String collectionName, String filter, String replacement, String updateOptions) { MongoCollection collection = getCollection(collectionName); Document filterDocument = Document.parse(filter); Document document = Document.parse(replacement); UpdateOptions options = new UpdateOptions(); if (updateOptions != null) { ObjectMapper mapper = new ObjectMapper(); try { JsonNode rootNode = mapper.readValue(updateOptions, JsonNode.class); options.upsert(rootNode.path("upsert").asBoolean()); } catch (IOException e) { e.printStackTrace(); } } UpdateResult updateResult = collection.replaceOne(filterDocument, document, options); return updateResult.getModifiedCount(); } @Override public long updateOne(String collectionName, String filter, String update) { return updateOne(collectionName, filter, update, null); } /** * @param collectionName * @param filter a document describing the query filter, which may not be null. * @param update a document describing the update, which may not be null. The update to apply must include only update operators. * @param updateOptions the options to apply to the update operation * { * upsert: * } * @return */ @Override public long updateOne(String collectionName, String filter, String update, String updateOptions) { MongoCollection collection = getCollection(collectionName); Document filterDocument = Document.parse(filter); Document document = Document.parse(update); UpdateOptions options = new UpdateOptions(); if (updateOptions != null) { ObjectMapper mapper = new ObjectMapper(); try { JsonNode rootNode = mapper.readValue(updateOptions, JsonNode.class); options.upsert(rootNode.path("upsert").asBoolean()); } catch (IOException e) { e.printStackTrace(); } } UpdateResult updateResult = collection.updateOne(filterDocument, document, options); return updateResult.getModifiedCount(); } @Override public long updateMany(String collectionName, String filter, String update) { return updateMany(collectionName, filter, update, null); } /** * @param collectionName * @param filter a document describing the query filter, which may not be null. * @param update a document describing the update, which may not be null. The update to apply must include only update operators. * @param updateOptions the options to apply to the update operation * { * upsert: * } * @return */ @Override public long updateMany(String collectionName, String filter, String update, String updateOptions) { MongoCollection collection = getCollection(collectionName); Document filterDocument = Document.parse(filter); Document document = Document.parse(update); UpdateOptions options = new UpdateOptions(); if (updateOptions != null) { ObjectMapper mapper = new ObjectMapper(); try { JsonNode rootNode = mapper.readValue(updateOptions, JsonNode.class); options.upsert(rootNode.path("upsert").asBoolean()); } catch (IOException e) { e.printStackTrace(); } } UpdateResult updateResult = collection.updateMany(filterDocument, document, options); return updateResult.getModifiedCount(); } @Override public String findOneAndDelete(String collectionName, String filter) { return findOneAndDelete(collectionName, filter, null); } /** * @param collectionName * @param filter the query filter to find the document with * @param options the options to apply to the operation * { * projection:, * sort: * } * @return */ @Override public String findOneAndDelete(String collectionName, String filter, String options) { MongoCollection collection = getCollection(collectionName); Document filterDocument = Document.parse(filter); FindOneAndDeleteOptions findOneAndDeleteOptions = new FindOneAndDeleteOptions(); if (options != null) { ObjectMapper mapper = new ObjectMapper(); try { JsonNode rootNode = mapper.readValue(options, JsonNode.class); String projection = rootNode.path("projection").toString(); Document projectionDoc = new Document(); if (!StringUtils.isEmpty(projection)) { Document.parse(projection); } String sort = rootNode.path("sort").toString(); Document sortDoc = new Document(); if (!StringUtils.isEmpty(sort)) { Document.parse(sort); } findOneAndDeleteOptions.projection(projectionDoc); findOneAndDeleteOptions.sort(sortDoc); } catch (IOException e) { e.printStackTrace(); } } Document document = collection.findOneAndDelete(filterDocument, findOneAndDeleteOptions); return document == null ? "{}" : document.toJson(); } @Override public String findOneAndReplace(String collectionName, String filter, String replacement) { return findOneAndReplace(collectionName, filter, replacement, null); } /** * @param collectionName * @param filter the query filter to apply the the replace operation * @param replacement the replacement document * @param options the options to apply to the operation * { * projection:, * sort:, * upsert: * } * @return */ @Override public String findOneAndReplace(String collectionName, String filter, String replacement, String options) { MongoCollection collection = getCollection(collectionName); Document filterDocument = Document.parse(filter); Document replacementDocument = Document.parse(replacement); FindOneAndReplaceOptions findOneAndReplaceOptions = new FindOneAndReplaceOptions(); if (options != null) { ObjectMapper mapper = new ObjectMapper(); try { JsonNode rootNode = mapper.readValue(options, JsonNode.class); String projection = rootNode.path("projection").toString(); Document projectionDoc = new Document(); if (!StringUtils.isEmpty(projection)) { Document.parse(projection); } String sort = rootNode.path("sort").toString(); Document sortDoc = new Document(); if (!StringUtils.isEmpty(sort)) { Document.parse(sort); } findOneAndReplaceOptions.projection(projectionDoc); findOneAndReplaceOptions.sort(sortDoc); findOneAndReplaceOptions.upsert(rootNode.path("upsert").asBoolean()); } catch (IOException e) { e.printStackTrace(); } } Document document = collection.findOneAndReplace(filterDocument, replacementDocument, findOneAndReplaceOptions); return document == null ? "{}" : document.toJson(); } @Override public String findOneAndUpdate(String collectionName, String filter, String update) { return findOneAndUpdate(collectionName, filter, update, null); } /** * @param collectionName * @param filter a document describing the query filter, which may not be null. * @param update a document describing the update, which may not be null. The update to apply must include only update operators. * @param options the options to apply to the operation * { * projection:, * sort:, * upsert: * } * @return */ @Override public String findOneAndUpdate(String collectionName, String filter, String update, String options) { MongoCollection collection = getCollection(collectionName); Document filterDocument = Document.parse(filter); Document updateDocument = Document.parse(update); FindOneAndUpdateOptions findOneAndUpdateOptions = new FindOneAndUpdateOptions(); if (options != null) { ObjectMapper mapper = new ObjectMapper(); try { JsonNode rootNode = mapper.readValue(options, JsonNode.class); String projection = rootNode.path("projection").asText(); Document projectionDoc = Document.parse(projection); String sort = rootNode.path("sort").asText(); Document sortDoc = Document.parse(sort); findOneAndUpdateOptions.projection(projectionDoc); findOneAndUpdateOptions.sort(sortDoc); findOneAndUpdateOptions.upsert(rootNode.path("upsert").asBoolean()); } catch (IOException e) { e.printStackTrace(); } } Document document = collection.findOneAndUpdate(filterDocument, updateDocument, findOneAndUpdateOptions); return document.toJson(); } @Override public void drop(String collectionName) { getCollection(collectionName).drop(); } @Override public String createIndex(String collectionName, String keys) { MongoCollection collection = getCollection(collectionName); Document keysDocument = Document.parse(keys); return collection.createIndex(keysDocument); } @Override public String createIndex(String collectionName, String keys, String indexOptions) { MongoCollection collection = getCollection(collectionName); Document keysDocument = Document.parse(keys); IndexOptions options = new IndexOptions(); //TODO:解析indexOptions // try { // ObjectMapper mapper = new ObjectMapper(); // JsonNode rootNode = mapper.readValue(indexOptions, JsonNode.class); // // // } catch (IOException e) { // e.printStackTrace(); // } return collection.createIndex(keysDocument, options); } @Override public List listIndexes(String collectionName) { MongoCollection collection = getCollection(collectionName); ListIndexesIterable indexes = collection.listIndexes(); List list = new ArrayList<>(); try (MongoCursor cursor = indexes.iterator()) { while (cursor.hasNext()) { Document doc = cursor.next(); list.add(doc.toJson()); } } return list; } @Override public void dropIndex(String collectionName, String indexName) { getCollection(collectionName).dropIndex(indexName); } @Override public void dropIndexes(String collectionName) { getCollection(collectionName).dropIndexes(); } @Override public void renameCollection(String collectionName, String newCollectionName) { MongoCollection collection = getCollection(collectionName); MongoNamespace namespace = collection.getNamespace(); collection.renameCollection(new MongoNamespace(namespace.getDatabaseName(), newCollectionName)); } @Override public void renameCollection(String collectionName, String newCollectionName, String renameCollectionOptions) { MongoCollection collection = getCollection(collectionName); MongoNamespace namespace = collection.getNamespace(); RenameCollectionOptions options = new RenameCollectionOptions(); try { ObjectMapper mapper = new ObjectMapper(); JsonNode rootNode = mapper.readValue(renameCollectionOptions, JsonNode.class); options.dropTarget(rootNode.path("dropTarget").asBoolean()); } catch (IOException e) { e.printStackTrace(); } collection.renameCollection(new MongoNamespace(namespace.getDatabaseName(), newCollectionName), options); } public MongoCollection getCollection(String collectionName) { MongoDatabase database = config.getDatabase(); return database.getCollection(collectionName); } public List listCollectionNames() { MongoDatabase database = config.getDatabase(); MongoIterable listCollectionNames = database.listCollectionNames(); List list = new ArrayList<>(); for (String collectionName : listCollectionNames) { list.add(collectionName); } return list; } }