mongo数组查询过滤,mongo中$numberLong型json转换---java

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);
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值