mongo数组查询过滤,mongo中long型json转换—java
这里使用的是mongo版本4.2.0
首先保证mongo.jar版本是3.10.2以上
注意:这里是java原生,不是spring
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.10.2</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-async</artifactId>
<version>3.10.2</version>
</dependency>
数据格式:
"_id" : 11,
"mailList" : [
{
"sendPlayerId" : 0,
"receivePlayerId" : 0,
"receiveTime" : 0,
"overTime" : 1575390131,
"delTime" : 0,
"useTime" : 0,
"useType" : 0,
"readType" : 0,
"delType" : 0,
"testTime" : NumberLong("1575354131034")
},
{
"mailId" : "9ac689dc-57fe-4035-a012-d55cce1c347b",
"sendPlayerId" : 0,
"receivePlayerId" : 0,
"receiveTime" : 0,
"overTime" : 1575390197,
"delTime" : 0,
"useTime" : 0,
"useType" : 0,
"readType" : 0,
"delType" : 0,
"testTime" : NumberLong("1575354197567")
}
]
上代码
需求是mailList中有多条数据,我们只取其中的某几条或者只对某一条做操作
private MongoClient mongoClient;
public MongoExecute(String uri) {
MongoClientOptions.Builder build = new MongoClientOptions.Builder();
build.connectionsPerHost(50);
build.threadsAllowedToBlockForConnectionMultiplier(50);
build.maxWaitTime(1000*60*2);
build.connectTimeout(1000*60*1);
build.maxConnectionIdleTime(60000);
build.maxConnectionLifeTime(600000);
MongoClientOptions myOptions = build.build();
mongoClient = new MongoClient(uri, myOptions);
/**
MongoClientURI mongoClientURI = new MongoClientURI(uri);
this.mongoClient = new MongoClient(mongoClientURI);
**/
}
//插入
public <T extends MongoModel> void insertUpdateAddList(String dbName, String collectionName, Map<String, Object> query, String listName, List<T> list) {
if (list == null || list.size() == 0) {
logger.error("MongoDBUtil INSERT_LISE ERROR:values is null");
return;
}
try {
DB db = this.mongoClient.getDB(dbName);
DBCollection dbCollection = db.getCollection(collectionName);
Gson gson = new Gson();
BasicDBList bdlist = new BasicDBList();
for(T t:list){
bdlist.add((DBObject) com.mongodb.util.JSON.parse(gson.toJson(t)));
}
BasicDBObject updateAdd = new BasicDBObject();
updateAdd.append(listName, new BasicDBObject("$each", bdlist));
BasicDBObject update = new BasicDBObject();
update.append("$addToSet", updateAdd);
BasicDBObject queryObj = new BasicDBObject();
for (Map.Entry<String, Object> entry : query.entrySet()) {
queryObj.append(entry.getKey(), entry.getValue());
}
dbCollection.update(queryObj, update,true ,true);
// WriteResult result = dbCollection.insert(objs);
// if (result.wasAcknowledged()) {
// return result.getN();
// }
} catch (Exception e) {
logger.error("MongoDBUtil INSERT_LISE ERROR", e);
}
}
/**
*查询
* @param dbName
* @param collectionName
* @param listName
* @param query
* @param sortName 排序字段
* @param sortType 查询获取数据 1表示升序,-1表示降序
* @param skip 分页起始id
* @param limit 一共查询多少条数据
* @return
*/
public <T extends MongoModel> List<T> aggregateSortLimit(String dbName, String collectionName,String listName,Map<String, Object> query,
String sortName,int sortType, int skip, int limit, Class<T> clazz) {
if (query == null || query.size() == 0) {
logger.error("MongoDBUtil aggregateSortLimit ERROR:query is null");
return null;
}
if (listName == null || "".equals(listName)) {
logger.error("MongoDBUtil aggregateSortLimit ERROR:listName is null");
return null;
}
List<T> dataList = new ArrayList<>();
try {
DB db = mongoClient.getDB(dbName);
DBCollection dbCollection = db.getCollection(collectionName);
List<BasicDBObject> list = new ArrayList<BasicDBObject>();
//将数组中的每一个元素转为每一条文档
BasicDBObject unwindObj = new BasicDBObject("$unwind", "$"+listName);
//简单的过滤文档,条件查询
BasicDBObject matchObj1 = new BasicDBObject();
for (Map.Entry<String, Object> entry : query.entrySet()) {
matchObj1.put(entry.getKey(), entry.getValue());
}
BasicDBObject matchObj = new BasicDBObject("$match", matchObj1);
//聚合
BasicDBObject projectObj1 = new BasicDBObject(listName, 1);
BasicDBObject projectObj = new BasicDBObject("$project", projectObj1);
//查询获取数据 1表示升序,-1表示降序
// BasicDBObject orderBy1 = new BasicDBObject(sortName, sortType);
// BasicDBObject orderBy = new BasicDBObject("$sort", orderBy1);
if(limit > 0){
BasicDBObject skipObj = new BasicDBObject("$skip", skip);
BasicDBObject limitObj = new BasicDBObject("$limit", limit);
list.add(skipObj);
list.add(limitObj);
}
list.add(unwindObj);
list.add(matchObj);
list.add(projectObj);
AggregationOptions aggregationOptions = AggregationOptions.builder().allowDiskUse(true).build();
Cursor cursor = dbCollection.aggregate(list,aggregationOptions);
// Cursor cursor = dbCollection.aggregate(list,AggregationOptions.builder().allowDiskUse(true).outputMode(AggregationOptions.OutputMode.CURSOR).build());
while(cursor.hasNext()) {
//这里我只需要数组数据,所以只取了数组字段
Object object = cursor.next().get(listName);
dataList.add(JSON.parseObject(object.toString(), clazz));
}
// List<DBObject> list = cursor.toArray();
} catch (Exception e) {
logger.error("MongoDBUtil aggregateSortLimit ERROR", e);
}
return dataList;
}
//删除
public <T extends MongoModel> void updateDeleteList(String dbName, String collectionName, Map<String, Object> query, String listName, Map<String, Object> update) {
if (update == null || update.size() == 0) {
logger.error("MongoDBUtil DEL_LISE ERROR:values is null");
return;
}
try {
DB db = this.mongoClient.getDB(dbName);
DBCollection dbCollection = db.getCollection(collectionName);
BasicDBObject queryObj = new BasicDBObject();
for (Map.Entry<String, Object> entry : query.entrySet()) {
queryObj.append(entry.getKey(), entry.getValue());
}
BasicDBObject updateObject = new BasicDBObject();
List<DBObject> companyList = new ArrayList();
for (Map.Entry<String, Object> entry : update.entrySet()) {
BasicDBObject delen = new BasicDBObject();
delen.append(entry.getKey(), entry.getValue());
companyList.add(delen);
}
updateObject.append("$or", companyList);
BasicDBObject del1 = new BasicDBObject();
del1.append(listName, updateObject);
BasicDBObject del = new BasicDBObject();
del.append("$pull", del1);
dbCollection.update(queryObj, del);
// WriteResult result = dbCollection.insert(objs);
// if (result.wasAcknowledged()) {
// return result.getN();
// }
} catch (Exception e) {
logger.error("MongoDBUtil DELETE_LISE ERROR", e);
}
}
//修改
public boolean updateColumn(String dbName, String collectionName,
Map<String, Object> query, Map<String, Object> newValues) {
if (query == null || query.size() == 0) {
logger.error("MongoDBUtil UPDATE ERROR: query is null");
return false;
}
if (newValues == null || newValues.size() == 0) {
logger.error("MongoDBUtil UPDATE ERROR: newValues is null");
return false;
}
BasicDBObject oldValue = new BasicDBObject();
for (Map.Entry<String, Object> entry : query.entrySet()) {
oldValue.put(entry.getKey(), entry.getValue());
}
BasicDBObject newValue = new BasicDBObject();
for (Map.Entry<String, Object> entry : newValues.entrySet()) {
newValue.put(entry.getKey(), entry.getValue());
}
BasicDBObject doc = new BasicDBObject();
doc.put("$set", newValue);
try {
DB db = mongoClient.getDB(dbName);
DBCollection dbCollection = db.getCollection(collectionName);
dbCollection.update(oldValue, doc, true, false);
} catch (Exception e) {
logger.error("MongoDBUtil UPDATE ERROR", e);
return false;
}
return true;
}
方法调用:
import com.alibaba.fastjson.JSON;
import com.mongodb.BasicDBObject;
import java.lang.reflect.Field;
import java.util.*;
public class MailDao {
private static final StarLogger logger = StarLogger.getInstance();
private static final MailDao instance = new MailDao();
private String mailMongoIndex = "Mail";
private String mailDbName = "Mail";
private String mailCollectionName = "Mail";
private String[] mailFindColumns;
private String[] mailFindWorldMailIdColumns = new String[]{"_id","worldMailId"};
private MongoExecute mongoExecute = MongoManager.getInstance().getMongo(mailMongoIndex);
private String worldMailCollectionName = "WorldMail";
private String[] worldMailFindColumns;
public static MailDao getInstance(){
return instance;
}
public void saveMail(Mail mail) {
mongoExecute.save(mailDbName, mailCollectionName, mail);
}
//获取存活的世界邮件
public List<WorldMail> getWorldMailList(){
int time = TimeUtil.getIntTimestamp();
Map<String, Object> query = new HashMap<String, Object>();
BasicDBObject overTime = new BasicDBObject("$gte", time);
query.put("overTime", overTime);
String obj = mongoExecute.find(mailDbName, worldMailCollectionName, worldMailFindColumns, query);
if(obj == null){
return null;
}
List<WorldMail> mailList = null;
if(!"".equals(obj)){
mailList = JSON.parseArray(obj, WorldMail.class);
}
return mailList;
}
//查询用户邮件中的世界邮件
public List<Mail> getPlayerWorld(int playerId){
int time = TimeUtil.getIntTimestamp();
Map<String, Object> query = new HashMap<String, Object>();
BasicDBObject worldMailId = new BasicDBObject("$ne", 0);
query.put("mailList.worldMailId", worldMailId);
query.put("_id", playerId);
List<Mail> mailList = mongoExecute.aggregateSortLimit(mailDbName, mailCollectionName, "mailList",query,"mailList.receiveTime", -1, 0, 0, Mail.class);
return mailList;
}
//小于过期时间 并且 未删除
public List<Mail> getMail(int playerId, int skip, int limit){
int time = TimeUtil.getIntTimestamp();
Map<String, Object> query = new HashMap<String, Object>();
BasicDBObject overTime1 = new BasicDBObject("$gt", time);
query.put("_id", playerId);
query.put("mailList.overTime", overTime1);
query.put("mailList.delType", 0);
List<Mail> mailList = mongoExecute.aggregateSortLimit(mailDbName, mailCollectionName, "mailList",query,"mailList.receiveTime", -1, skip, limit, Mail.class);
if(mailList == null){
return null;
}
return mailList;
}
//查询单个邮件
public Mail getMailById(int playerId, String mailId){
int time = TimeUtil.getIntTimestamp();
Map<String, Object> query = new HashMap<String, Object>();
query.put("_id", playerId);
query.put("mailList.mailId", mailId);
Mail mail = mongoExecute.aggregateFindOne(mailDbName, mailCollectionName, "mailList",query,Mail.class);
return mail;
}
public void addMailList(int playerId, List<Mail> mailList){
if(mailList == null || mailList.size() < 1){
return;
}
Map<String, Object> query = new HashMap<String, Object>();
query.put("_id", playerId);
mongoExecute.insertUpdateAddList(mailDbName, mailCollectionName, query, "mailList", mailList);
}
public void deleteMail(int playerId){
int time = TimeUtil.getIntTimestamp();
Map<String, Object> query = new HashMap<String, Object>();
query.put("_id", playerId);
Map<String, Object> update = new HashMap<String, Object>();
BasicDBObject deleteTime = new BasicDBObject("$lte", time);
update.put("delTime",deleteTime);
update.put("mailList.delType", 1);
mongoExecute.updateDeleteList(mailDbName, mailCollectionName, query, "mailList", update);
}
public void updateMail(int playerId, String mailId, Map<String, Object> update){
Map<String, Object> query = new HashMap<String, Object>();
query.put("_id", playerId);
query.put("mailList.mailId", mailId);
// BasicDBObject mailIdbd = new BasicDBObject("mailList.mailId",mailId);
// BasicDBObject elemMatchbd = new BasicDBObject("$elemMatch",mailIdbd);
// query.put("mailList",elemMatchbd);
mongoExecute.updateColumn(mailDbName, mailCollectionName, query, update);
}
private String[] getWorldMailFiledName(){
if(worldMailFindColumns == null) {
Field[] fields = WorldMail.class.getDeclaredFields();
worldMailFindColumns = new String[fields.length];
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
CacheFieldAnnotation cacheFieldAnnotation = field.getAnnotation(CacheFieldAnnotation.class);
if(cacheFieldAnnotation.value()) {
worldMailFindColumns[i] = field.getName();
}
}
}
return worldMailFindColumns;
}
private String[] getPlayerMailFiledName(){
if(mailFindColumns == null) {
Field[] fields = PlayerMail.class.getDeclaredFields();
mailFindColumns = new String[fields.length];
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
CacheFieldAnnotation cacheFieldAnnotation = field.getAnnotation(CacheFieldAnnotation.class);
if(cacheFieldAnnotation.value()) {
mailFindColumns[i] = field.getName();
}
}
}
return mailFindColumns;
}
}
需要注意的是,mongo 存储的long型需要自己处理,json会序列化失败
一般格式为 “XXX”:{"$numberLong":123456789}
这里我们自己处理
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import io.netty.util.internal.StringUtil;
import java.lang.reflect.Type;
/**
*自定义fastjson的反序列化器
*/
public class MongoLongConverter implements ObjectDeserializer {
@Override
public Long deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
String longStr = parser.parseObject().getString("$numberLong");
if (!StringUtil.isNullOrEmpty(longStr)){
return Long.parseLong(longStr);
}
return 0L;
}
@Override
public int getFastMatchToken() {
return 0;
}
}
使用方法是加到需要转成的对象的属性上
@JSONField(deserializeUsing =MongoLongConverter.class)
private long lastLandingTime = 0L;
可能会缺少一些类,如果有需要的同学请在下方留言,我尽量补上
更新=======================================
上边的方法只能转换
"testTime": {"$numberLong": "1575534543764"}
这种格式,但是mongo中对于存储实际值非long型不会自动加入$numberLong", 而且很不方便,所以应该定义和使用自定义JsonWriterSettings来微调JSON生成:
public class MongoExecute{
private static final JsonWriterSettings settings = JsonWriterSettings.builder().int64Converter((value, writer) -> writer.writeNumber(value.toString())).build();
/**
*
* @param dbName
* @param collectionName
* @param listName
* @param query
* @param sortName 排序字段
* @param sortType 查询获取数据 1表示升序,-1表示降序
* @param skip 分页起始id
* @param limit 一共查询多少条数据
* @return
*/
public <T extends MongoModel> List<T> aggregateSortLimit(String dbName, String collectionName,String listName,Map<String, Object> query,
String sortName,int sortType, int skip, int limit, Class<T> clazz) {
if (query == null || query.size() == 0) {
logger.error("MongoDBUtil aggregateSortLimit ERROR:query is null");
return null;
}
if (listName == null || "".equals(listName)) {
logger.error("MongoDBUtil aggregateSortLimit ERROR:listName is null");
return null;
}
List<T> dataList = new ArrayList<>();
try {
DB db = mongoClient.getDB(dbName);
DBCollection dbCollection = db.getCollection(collectionName);
List<BasicDBObject> list = new ArrayList<BasicDBObject>();
//将数组中的每一个元素转为每一条文档
BasicDBObject unwindObj = new BasicDBObject("$unwind", "$"+listName);
//简单的过滤文档,条件查询
BasicDBObject matchObj1 = new BasicDBObject();
for (Map.Entry<String, Object> entry : query.entrySet()) {
matchObj1.put(entry.getKey(), entry.getValue());
}
BasicDBObject matchObj = new BasicDBObject("$match", matchObj1);
//聚合
BasicDBObject projectObj1 = new BasicDBObject(listName, 1);
BasicDBObject projectObj = new BasicDBObject("$project", projectObj1);
//查询获取数据 1表示升序,-1表示降序
// BasicDBObject orderBy1 = new BasicDBObject(sortName, sortType);
// BasicDBObject orderBy = new BasicDBObject("$sort", orderBy1);
if(limit > 0){
BasicDBObject skipObj = new BasicDBObject("$skip", skip);
BasicDBObject limitObj = new BasicDBObject("$limit", limit);
list.add(skipObj);
list.add(limitObj);
}
list.add(unwindObj);
list.add(matchObj);
list.add(projectObj);
AggregationOptions aggregationOptions = AggregationOptions.builder().allowDiskUse(true).build();
Cursor cursor = dbCollection.aggregate(list,aggregationOptions);
// Cursor cursor = dbCollection.aggregate(list,AggregationOptions.builder().allowDiskUse(true).outputMode(AggregationOptions.OutputMode.CURSOR).build());
while(cursor.hasNext()) {
Object object = cursor.next().get(listName);
// JsonWriterSettings settings = JsonWriterSettings.builder().int64Converter((value, writer) -> writer.writeNumber(value.toString())).build();
String js = Document.parse(object.toString()).toJson(settings);
System.out.println("Mail----------"+object.toString());
System.out.println("bd----------"+js);
dataList.add(JSON.parseObject(js, clazz));
}
// List<DBObject> list = cursor.toArray();
} catch (Exception e) {
logger.error("MongoDBUtil aggregateSortLimit ERROR", e);
}
return dataList;
}
}
方法来源 :http://www.it1352.com/965721.html
也可以使用这种方式
String str1 = "{fristIn": {"$numberLong": "1575517381"}}"
Document d = org.bson.Document.parse(str1);
String js = com.mongodb.util.JSON.serialize(d);
System.out.println(js);
Player mail = JSON.parseObject(js, Player.class);