MongoDB的使用

MongoDB 是一个跨平台的,以 JSON 为数据模型的文档数据库,是当前 NoSQL 数据库产品中最热门的一种。它介于关系数据库和非关系数据库之间,是非关系数据库当中功能最丰富,最像关系数据库的产品。

1、 MongoDB 与 MySQL 数据库

  •  数据库操作
--创建数据库
use db1
--查看数据库
show dbs
--删除数据库
db.dropDatabase()
  •  集合操作
--创建集合
db.createCollection("users")
--查看集合
show collections
--删除集合
db.users.drop()

2、mongoDB数据操作

2.1、文档的插入操作

注意:在 MongoDB 中不需要提前创建集合就可以直接插入文档,在插入文档的同时自动创建集合

  • 插入文档
db.fruits.insert(
    [
        { "name": "apple", "price": 10, "color": ["red", "green"], },
        { "name": "banana", "price": 8, "color": ["yellow", "green"], },
        { "name": "mongo", "price": 12, "color": ["yellow", "green"], },
    ]
)
  • 插入一条文档
db.users.insertOne(
    {
        "username": "zhangsan",
        "password": "88888888",
        "form": { "country": "China", "city": "Beijing" }
    }
)
  • 插入多条文档
db.users.insertMany(
    [
        {
            "username": "lisi",
            "password": "4444",
            "form": { "country": "China", "city": "Shanghai" }
        },
        {
            "username": "wanger",
            "password": "666666",
            "form": { "country": "China", "city": "Shenzhen" }
        },
    ]
)

2.2、文档的查询操作

  • 单条件查询文档
db.users.find(
    { "username": "zhangsan" }
)
  • 多条件 and 查询文档
db.users.find(
    { "username": "zhangsan", "password": "88888888" }
)
  • 多条件 and 查询文档的另一种形式
db.users.find(
    {
        $and: [
            { "username": "zhangsan" },
            { "password": "88888888" }
        ]
    }
)
  • 多条件 or 查询文档
db.users.find(
    {
        $or: [
            { "username": "zhangsan" },
            { "password": "88888888" }
        ]
    }
)
  • 多条件in 
db.users.find(
    {
      "userid":{"$in":["1","2"]}
    } 
)
  • 正则表达式查询文档(模糊查询) 
// mysql
select * from member where name like ‘%XXX%’

// 字段为开头或结尾的文档
db.member.find({“name”:{ $regex:/XXX/ }})

// 字段为开头的文档
db.member.find({“name”:{$regex:/^XXX/}})

// 字段为结尾的文档
db.member.find({“name”:{$regex:/XXX^/}})

// 忽略大小写
db.member.find({“name”:{$regex:/XXX/i}})

// java中正则使用
Pattern pattern = Pattern("^.111222.*$",Pattern.CASE_INSENSITIVE);
Map<String,Object> map = new HashMap<>();
map.put("$regex",pattern);
Map<String,Object> filterMap = new HashMap<>();
filterMap.put("name",map);

  • 比较大小
db.users.find(
    {
        "createdAt":{"$gte":"20231014","$lte":"20231015"}
    }
)
  • 查询返回的字段
db.fruits.find(
    { "name": "apple" }, { "_id": 0, "name": 1, "color": 1 }
)

注意:其中 _id name color 的 0 表示不返回字段,其中的 1 表示返回字段

  • and与or使用
db.METRIC_LAST_MAIN_10.find
    ({
       "$and":[
           {"CI_INFO.SECZONEID":{"$exists":true}},
           {"CI_METRIC.IPV4ADDR.VALUE":{"$exists":false}},
           {"CI_METRIC.IPADDR.VALUE":{"$exists":false}},
           {"CI_INFO.IPV4ADDR.VALUE":{"$exists":false}},
           {"CI_INFO.IPADDR.VALUE":{"$exists":false}},
           {"CI_TYPE":{"$in":["AIX","HSERVER","LINUX","UNIX","VSERVER","WINDOWS","LOADBALANCER","ROUTER","SWITCH","FIREWALL","IDS","IPS","ISOLATION","TRAFFICMONITOR","VPN","WAF"]}}
        ],
		"$or":[{"CI_INFO.IPV6ADDR.VALUE":{"$exists":true}},{"CI_METRIC.IPV6ADDR.VALUE":{"$exists":true}}]
    })
.projection({})
.sort({_id:-1})
.limit(100)

2.3、文档的更新操作 

  • 更新一条文档
db.fruits.updateOne(
    { "name": "banana" }, { $set: { "price": 20 } }
)

注意:updateOne 不管查询到多少条文档都只更新第一条文档

  • 更新多条文档
db.fruits.updateMany(
    { "name": "banana" }, { $set: { "price": 20 } }
)

注意:updateMany 查询到多少条文档就更新多少条文档

  • 更新数组操作符

2.4、文档的删除操作

  • 删除 price = 10 的文档

db.fruits.remove(
    { "price": 10 }
)
  • 删除 price < 12 的文档
db.fruits.remove(
    { "price": { $lt: 12 } }
)
  • 删除所有文档
db.fruits.remove({})

3、聚合分组

在 MongoDB 中聚合查询 aggregate 是以管道的形式进行处理数据并主要用于处理数据统计、平均值、求和等

  • 聚合查询
db.fruits.aggregate(
    [
        { $group: { _id: "$name", total: { $sum: 1 } } },
        { $project: { name: "$name", total: "$total" } },
    ]
)

注意:这里对 fruits 集合进行聚合查询,先按 name 字段进行分组并合计分组的数量,然后在返回 name 字段和分组后的 total 字段进行显示 

  • match与group
db.METRIC_LAST_MAIN_10.aggregate([
    {"$match":
        {
        "$and":[
           {"CI_INFO.SECZONEID":{"$exists":true}},
           {"CI_METRIC.IPV4ADDR.VALUE":{"$exists":false}},
           {"CI_METRIC.IPADDR.VALUE":{"$exists":false}},
           {"CI_INFO.IPV4ADDR.VALUE":{"$exists":false}},
           {"CI_INFO.IPADDR.VALUE":{"$exists":false}},
           {"CI_TYPE":{"$in":["AIX","HSERVER","LINUX","UNIX","VSERVER","WINDOWS","LOADBALANCER","ROUTER","SWITCH","FIREWALL","IDS","IPS","ISOLATION","TRAFFICMONITOR","VPN","WAF"]}}
        ],
        "$or":[{"CI_INFO.IPV6ADDR.VALUE":{"$exists":true}},{"CI_METRIC.IPV6ADDR.VALUE":{"$exists":true}}]
        }
    },
    {"$group":{
        _id:{
		    "SECZONEID":"$CI_INFO.SECZONEID",
            "BC_ID":"$CI_INFO.SECZONEID",
            "BCNAME":"$CI_INFO.BCNAME"
        },
        count:{$sum:1}
    }}
    ])
.projection({})
.sort({_id:-1})
.limit(100)
db.METRIC_LAST_MAIN_10.aggregate()
    .match({
        "$and":[
           {"CI_INFO.SECZONEID":{"$exists":true}},
           {"CI_METRIC.IPV4ADDR.VALUE":{"$exists":false}},
           {"CI_METRIC.IPADDR.VALUE":{"$exists":false}},
           {"CI_INFO.IPV4ADDR.VALUE":{"$exists":false}},
           {"CI_INFO.IPADDR.VALUE":{"$exists":false}}, 
           {"CI_TYPE":{"$in":["AIX","HSERVER","LINUX","UNIX","VSERVER","WINDOWS","LOADBALANCER","ROUTER","SWITCH","FIREWALL","IDS","IPS","ISOLATION","TRAFFICMONITOR","VPN","WAF"]}}
        ],
        "$or":[{"CI_INFO.IPV6ADDR.VALUE":{"$exists":true}},{"CI_METRIC.IPV6ADDR.VALUE":{"$exists":true}}]
    })
    .group({
        _id:{
		    "SECZONEID":"$CI_INFO.SECZONEID",
            "BC_ID":"$CI_INFO.SECZONEID",
            "BCNAME":"$CI_INFO.BCNAME"
        },
        count:{$sum:1}
    })
// sort()方法进行升序排序
db.collection.find().sort({field: 1})
// sort()方法进行降序排序
db.collection.find().sort({field: -1})
  • 常用聚合查询对照表

  • 聚合表达式

3.1 、单一字段分组

分组后不会展示其他字段, _id为固定写法,userid为分组字段

# 比如对比sql:select userid from testgroup by userid
db.test.aggregate({"$group":{"_id":"$userid"}} )

 3.2、多字段分组 

_id为固定写法,userid与articleid为分组字段,多字段时需要设置一个别名

# 比如对比sql:select userid,articleid from testgroup by userid,articleid
db.test.aggregate({"$group":{"_id":{"userid":"$userid","articleid":"$articleid"}}})

3.3、条件匹配分组 

$match表示匹配条件,在group前表示where,在后表示having,userid为分组字段

# 比如对比sql:select userid from test where userid in("1","2") group by userid
db.test.aggregate(
    {"$match":{"userid":{"$in":["1","2"]}}},
    {"$group":{"_id":"$userid"}}
)
或者
# 比如对比sql:select userid,articleid from test where userid in("1","2")  group by userid
db.test.aggregate(
    {"$match":{"userid":{"$in":["1","2"]}}},
    {"$group":{"_id":{"userid":"$userid","articleid":"$articleid"}}}
)
或者having聚合查询
# 比如:select userid,avg(price) as avg from test where userid >'10' group by userid having avg>35
db.test.aggregate(
    {"$match":{"userid":{"$gt":"10"}}},
    {"$group":{"_id":"$userid",'avg':{"$avg":"$price"}}},
    {"$match":{"avg":{"$gt":35}}}
)

3.4、分组分页排序 

限制:$limit、跳过:$skip

db.test.aggregate(
        {"$group":{"_id":"$userid"}},
        {"$skip":1},
        {"$limit":2}
	)

4、聚合查询

聚合分组,分为:$sum、$avg、$max、$min、$first、$last,聚合结果需要使用别名,并且可以结合条件和排序等元素

  新增数据:

    db.test.insert([{
        "articleid":"1",
        "price":200,
        "userid":"5"
    },{
        "articleid":"2",
        "price":300,
        "userid":"5"
    },{
        "articleid":"3",
        "price":400,
        "userid":"5"
    },{
        "articleid":"1",
        "price":200,
        "userid":"6"
    },{
        "articleid":"2",
        "price":300,
        "userid":"7"
    }]);

4.1、sum聚合-求数值总和 

求某个数值总和,userid分组字段[可以用于多字段聚合],{"$sum":$price}表示求price合计

db.test.aggregate({"$group":{"_id":"$userid","total":{"$sum":"$price"}}})

4.2、sum聚合-求分组后数量  

db.test.aggregate({"$group":{"_id":"$userid","total":{"$sum":1}}})

4.3、avg、max、min聚合 

avg、max、min可以分开使用,也可以一起使用

db.test.aggregate({"$group":{"_id":"$userid","avg":{"$avg":"$price"},"max":{"$max":"$price"},"min":{"$min":"$price"}}})

4.4、复合聚合 

可以多字段聚合求值,通过sumavg、max、min进行组合

db.test.aggregate({"$group":{"_id":"$userid"
	,"total":{"$sum":"$price"}
	,"avg":{"$avg":"$price"}}})

4.5、聚合分组排序 

对聚合结果进行排序,$sort-排序,avg-聚合结果的别名,1:升序,-1:降序

# 先按userid降序,再avg升序
	db.test.aggregate({"$group":{"_id":"$userid"
	,"avg":{"$avg":"$price"}}}
	,{"$sort":{"avg":1}}
	,{"$sort":{"_id":-1}})

4.6、首尾取值聚合

$first-第一个元素、$last-最后一个元素

vdb.test.aggregate({"$group":{"_id":"$userid","prices":{"$first":"$price"}}})

4.7、聚合分组拼接 

等同于group_concat,$push-元素可重复,$addToSet-元素不可重复,将分组后的数据拼接为一个数组

db.test.aggregate({"$group":{"_id":"$userid","names":{"$push":"$price"}}})

5、索引 

不同于MySQL的索引, mongo的索引是有方向的, value代表了索引的方向, 这个特性在排序的使用很好用。1 代表升序, -1代表降序

5.1、索引的优缺点

优点:

  • 查询速率很快
  • 大大减少了服务器需要扫描的数据量
  • 索引可以将随机io转换为顺序io

缺点:

  • 降低插入速度
  • 浪费存储空间,删除空间不会释放字段(需要通过命令来整理碎片,这个过错比较缓慢)导致mongodb占用空间会比较大
  • 不适当的查询语句,会导致并未使用索引

5.2、无法使用索引的操作

  • where和exists无法使用索引,$exists操作, 会遍历每个文档,以确定字段是否存在, $where会同样的遍历每个文档。
  • 类似MySQL, 在mongo中使用取反的查询操作, 也会导致索引利用效率低下, 或者不会使用索引, 例如$ne, 而$not虽然有时能够使用索引, 但是通常它并不知道该如何利用索引。
  • $nin, 总是扫描整个集合。

5.3、索引类型

MongoDB 中索引的类型:单键索引、复合索引、多键值索引、地理索引、全文索引、 散列索引。

5.3.1、单键索引
db.collection.createIndex({filedName: value})
5.3.2、 复合索引 

索引是区分方向的:

db.users.createIndex({"name": 1, "age": 1}) 与 db.users.createIndex({"name": 1, "age": -1})是两个不同的索引。只有要针对多个字段进行排序时, 索引的方向才是重要的, mongo会自动的翻转索引, 也就是说{"name": 1}与{"name": -1}在使用时是一致的。{"name": 1, "age": 1}与 {"name": -1, "age": -1}也是一致的。

索引字段要有序:

为了能够更加有效的利用索引, 用于精确匹配的字段应该放在索引的前面, 范围字段放在后面, 这样mongo就能利用精确匹配过滤掉大部分文档, 然后利用之后的索引去再次过滤结果。例如我们要查询name=user10&age>20, 那么我们的索引应该是{"name": 1, "age": 1}, 而不是{"age": 1, "name": 1}

隐式索引:

如果我们创建一个复合索引{"name": 1, "age": 1, "created": -1}, 当利用{"name": 1}进行排序的时候, 也能够使用前面创建的索引, 注意, 必须是从左往右依次匹配才行, 也就是说{"age": 1}, 这种是不会用到索引的。

5.3.3、多键值索引

若要为包含数组的字段建立索引,MongoDB 会为数组中的每个元素创建索引键。这些多键值索引支持对数组字段的高效查询
需要注意的是,如果集合中包含多个待索引字段是数组,则无法创建复合多键索引。

db.users.insert ({item : “ABC”, ratings: [ 2, 5, 9 ]})
db.users.createIndex({ratings:1})
db.users.find({ratings:2}).explain()
5.3.4、唯一索引 

类似MySQL的唯一约束, mongo也是具有的, 用来保证一个集合内相同字段值的唯一性

db.users.createIndex({"name": 1}, {"unique": true, "name": index_name})

5.3.5、TTL索引 

创建了一个TTL索引, mongo会每分钟检查一次索引, 并删除过期的文档。这个索引可以用来排序和搜索。

db.collection.createIndex({"name": 1}, {"expireAfterSeconds": 10*60})

5.4、索引操作 

5.4.1、删除索引
//删除一个索引
db.collection.dropIndex("index_name")

//删除所有索引
db.collection.dropIndexes()
5.4.2、explain()

mongo也有explain方法, 去查看索引的使用情况db.users.find({"name": "user100"}).explain()就能查看是否使用了索引, 以及其他的一些详细信息, 包括, 使用的索引, 扫描的文档数据, 结果的数量, 查询用时等等。

db.users.find({"name": "user100"}).explain(1)可以查看查询过程

{
    "queryPlanner": {  # 查询计划
        "plannerVersion": NumberInt("1"),  # 计划版本
        "namespace": "db_name.collection_name",  # 命名空间,作用于哪个库的哪个集合
        "indexFilterSet": false,  # 是否对查询使用索引过滤
        "parsedQuery": {  # 解析查询条件
            "index_key_name": {
                "$eq": 1
            }
        },
        "queryHash": "6ACB91B3",  # 仅对查询条件进行hash的16进制字符串,帮助识别相同查询条件的 其他查询操作或写操作
        "planCacheKey": "ACADC259",  # 和查询关联的计划缓存的hash键
        "winningPlan": {  # 查询优化器 选择的最优执行计划,此计划包含多个 树状结构的子阶段(一个查询计划需要多个阶段来完成);
            "stage": "FETCH",  # 父阶段;查询方式
            "inputStage": {  # 子阶段
                "stage": "IXSCAN",  # 子阶段的查询方式
                "keyPattern": {  # 索引模式
                    "index_key_name": 1
                },
                "indexName": "index_key_name_1",  # 索引名称
                "isMultiKey": false,  # 是否是复合索引
                "multiKeyPaths": {  # 复合索引路径
                    "index_key_name": []
                },
                "isUnique": true,  # 是否是唯一索引
                "isSparse": false,  # 是否是稀疏索引
                "isPartial": false,  # 是否是部分索引
                "indexVersion": NumberInt("2"),  # 索引版本
                "direction": "forward",  # 索引方向
                "indexBounds": {  # 索引查询的范围边界
                    "index_key_name": [  # 创建索引的key
                        "[1.0, 1.0]"  # 边界范围
                    ]
                }
            }
        },
        "rejectedPlans": []  # 查询又花钱 拒绝的执行计划
    },
    "executionStats": {  # 详细的执行统计信息
        "executionSuccess": true,  # 是否执行成功
        "nReturned": NumberInt("0"),  # 符合查询条件的文档个数
        "executionTimeMillis": NumberInt("0"),  # 选择某个查询计划和执行查询 所耗费的总时间(毫秒)
        "totalKeysExamined": NumberInt("0"),  # 扫描的索引总行数
        "totalDocsExamined": NumberInt("0"),  # 扫描的文档总次数(即使同一个文档如果被扫描2次,则此值为2),常见于 stage为 COLLSCAN/FETCH
        "executionStages": {  # 用树状形式 描述 详细的执行计划
            "stage": "FETCH",  # 查询方式
            "nReturned": NumberInt("0"),
            "executionTimeMillisEstimate": NumberInt("0"),  # 估计执行时间(毫秒)
            "works": NumberInt("1"),  # 指定查询执行阶段执行的“工作单元”的数量。查询执行将其工作划分为小单元。
            # “工作单元”可能包括检查单个索引键、从集合中获取单个文档、对单个文档应用投影或进行内部簿记
            "advanced": NumberInt("0"),  # 由这一阶段返回到它的父阶段的中间结果或高级结果的数量。
            "needTime": NumberInt("0"),  # 未将中间结果提前到其父阶段的工作循环数
            "needYield": NumberInt("0"),  # 为了让写操作执行,而让出读锁的次数
            "saveState": NumberInt("0"),  # 查询阶段暂停处理并保存其当前执行状态的次数,例如准备放弃其锁
            "restoreState": NumberInt("0"),  # 查询阶段恢复已保存的执行状态的次数,例如,在恢复以前生成的锁之后。
            "isEOF": NumberInt("1"),  # 执行阶段是否已到达最后一个; 1:是 0:不是
            "docsExamined": NumberInt("0"),  # 扫描文档总次数
            "alreadyHasObj": NumberInt("0"),
            "inputStage": {
                "stage": "IXSCAN",
                "nReturned": NumberInt("0"),
                "executionTimeMillisEstimate": NumberInt("0"),
                "works": NumberInt("1"),
                "advanced": NumberInt("0"),
                "needTime": NumberInt("0"),
                "needYield": NumberInt("0"),
                "saveState": NumberInt("0"),
                "restoreState": NumberInt("0"),
                "isEOF": NumberInt("1"),
                "keyPattern": {
                    "index_key_name": 1
                },
                "indexName": "index_key_name_1",
                "isMultiKey": false,
                "multiKeyPaths": {
                    "index_key_name": []
                },
                "isUnique": true,
                "isSparse": false,
                "isPartial": false,
                "indexVersion": NumberInt("2"),
                "direction": "forward",
                "indexBounds": {
                    "index_key_name": [
                        "[1.0, 1.0]"
                    ]
                },
                "keysExamined": NumberInt("0"),  # 通过索引扫描的文档总个数
                "seeks": NumberInt("1"),  # 为了完成索引扫描,必须将索引游标搜索到新位置的次数。
                "dupsTested": NumberInt("0"),
                "dupsDropped": NumberInt("0")
            }
        },
        "allPlansExecution": []  # 在计划选择阶段,获胜计划和被拒绝计划的部分执行信息
    },
    "serverInfo": {  # mongo服务信息
        "host": "aa8f4be",
        "port": NumberInt("27010"),
        "version": "4.2.0",
        "gitVersion": "a4b751dcf51dd249c5865812b390cfd"
    },
    "ok": 1
}

executionTimeMillis执行时间为937毫秒 

6、java中使用

6.1、aggregate Document

 public  static AggregateIterable<Document> groupCountBySiteId(String devId, String dataType, String startDateTime, String endDateTime, String fileName, String collectionName) {
        //连接数据库  collectionName
        MongoDatabase md = MongoManager.getMongoInstance().getDatabase(collectionName);
        //创建sql
        List<Document> dbObjects = new ArrayList<>();
        //用来写查询的
        Document document=new Document();
        document.append("did",devId);
        document.append("datatype",dataType);
        document.append("time",new Document().append("$gte", startDateTime).append("$lte", endDateTime));
        //where
        Document match =new Document("$match",document);
        Document sub_project =new Document();
        //截取用来分组的时间 用来group
        sub_project.put("time",new Document("$substrBytes", Arrays.asList(new Object[]{"$time",0,13})));
        sub_project.put("value","$value");
        Document project = new Document("$project",sub_project);
        //group
        Document sub_group = new Document();
        sub_group.put("_id","$time");
        sub_group.put("value",new Document("$first","$value"));
        sub_group.put("time",new Document("$first","$time"));
        Document group = new Document("$group",sub_group);
        //order by
        Document sort = new Document("$sort",new Document("time", 1));
        dbObjects.add(match);
        dbObjects.add(project);
        dbObjects.add(group);
        dbObjects.add(sort);
        AggregateIterable<Document> x =md.getCollection(fileName).aggregate(dbObjects);
        MongoCursor<Document> it=x.iterator();
        while (it.hasNext()){
            Document document1=it.next();
            System.out.println(document1.toJson());
        }
        return x;
    }

6.2、aggregate BasicDBObject

public void queryAggregates() {
	// match(相当于 WHERE 或者 HAVING )
	BasicDBObject query= new BasicDBObject();
	BasicDBObject[] array = { new BasicDBObject("time", new BasicDBObject("$gte", "2018-09-12")),new BasicDBObject("time", new BasicDBObject("$lte","2018-12-25"))};
	query.append("$and", array);
	BasicDBObject match = new BasicDBObject("$match", query); 
	// group(相当于 GROUP BY)
	BasicDBObject group = new BasicDBObject("$group", new BasicDBObject("_id", "$subject")
				.append("count", new BasicDBObject("$sum", 1)));
	// sort(排序)
	BasicDBObject sort = new BasicDBObject("$sort", new BasicDBObject("count", -1));//1:正序,-1倒序
	// skip(跳过前面多少条数据,分页时使用)
	//limt(只要前多少条数据,分页时使用)
	BasicDBObject limit = new BasicDBObject("$limit", pageSize);
	BasicDBObject skip = new BasicDBObject("$skip", (pageNo - 1) * pageSize);
	// queryList集合里的**顺序不能乱**,否则会报错。 
	List<DBObject> queryList = new ArrayList<>();
	queryList.add(match);
	queryList.add(group);
	queryList.add(sort);
	queryList.add(skip);
	queryList.add(limit);
	// 变量dbName,动态指向DB
	AggregateIterable<Document> iterable = mongoClient.mongoClient.getDatabase(dbName).getCollection(gatherName).aggregate(queryList);
	for (Document document : aggregate) {
            Object users = document.get("users");
            System.out.println(users);
        }
	 
}

6.3、aggregate Bson

public void queryAggregates() {
	List<Bson> bsonList = new ArrayList<>();
	// match
	Bson filters = Filters.and(Filters.eq("aaa", '111'));
	filters = Filters.and(filters,Filters.eq("bbb", '222'));
	Bson match= Aggregates.match(filters);
	// group
	Document groupKeyDoc = new Document();
	groupKeyDoc.put("aaa","111");
	groupKeyDoc.put("bbb","222");
	groupKeyDoc.put("ccc","333");
	BsonField bsonFiled = Accumulators.sum("count",1);
	Bson group  =Aggregates.group(groupKeyDoc,bsonFiled );
	// sort
	Bson sort = Aggregates.sort(Sorts.descending("aaa"));
	// limit
	Bson limit = Aggregates.limit(pageSize);
	// skip
	Bson skip = Aggregates.skip(pageSize * (pageNo - 1));
	// project 
	Bson project = Aggregates.project(Projections.slice("aaa", 2,3));
	bsonList.add(match);
	bsonList.add(group  );
	bsonList.add(sort);
	bsonList.add(limit);
	bsonList.add(skip );
	bsonList.add(project);
	AggregateIterable<Document> aggregate = c.aggregate(bsonList);
	for (Document document : aggregate) {
		Object users = document.get("users");
		System.out.println(users);
	}
}

6.4、Aggregation

public PageForm queryForPage(QueryForm queryForm,
                             String companyId,
                             Set<String> suitOrgCodeSet,
                             String postKey,
                             String postName,
                             Integer recruitType,
                             String workPlaceCode,
                             String postTypeCode,
                             String orgCode,
                             String siteCode,
                             String salaryCode,
                             String educationCode,
                             Date publishBeginDate) {
 
    // 构建查询条件
    Criteria criteria = Criteria.where("companyId").is(companyId);
 
    // 适用机构列表
    List<Criteria> criterias = new ArrayList<>();
    for(String suitOrgCode:suitOrgCodeSet){
        Criteria newCriteria = Criteria.where("orgCode").regex(suitOrgCode + "($|/.*)");
        criterias.add(newCriteria);
    }
    Criteria[] result = criterias.toArray(new Criteria[criterias.size()]);
    criteria.orOperator(result);
 
    // 招聘类型
    criteria.and("recruitType").is(recruitType);
 
    // 职位名称(模糊查询)
    if(StringUtils.isNotBlank(postName)){
        criteria.and("externalPostName").regex(".*" + postName + ".*");
    }
    // 职位关键字(模糊查询)
    if(StringUtils.isNotBlank(postKey)){
        criteria.and("postKeySearch").regex(".*" + postKey + ".*");
    }
    // 学历
    if(StringUtils.isNotBlank(educationCode)){
        criteria.and("educationCode").is(educationCode);
    }
    // 工作地点
    if(StringUtils.isNotBlank(workPlaceCode)){
        // 数组中元素的具体查询
        //criteria.and("workPlaceCodeList").elemMatch(new Criteria().in(workPlaceCode));
        // 数组中元素的正则匹配的模糊查询
        criteria.and("workPlaceCodeList").elemMatch(new Criteria("$regex").is(workPlaceCode + "($|/.*)"));
    }
    // 职位类型(匹配当前职位类型及其以下职位类型)
    if(StringUtils.isNotBlank(postTypeCode)){
        criteria.and("postTypeCode").regex(postTypeCode + "($|/.*)");
    }
    // 所属机构(匹配当前机构及其以下机构)
    if(StringUtils.isNotBlank(orgCode)){
        criteria.and("orgCode").regex(orgCode + "($|/.*)");
    }
    // 站点
    if(StringUtils.isNotBlank(siteCode)){
        criteria.and("siteCodeList").elemMatch(new Criteria().in(siteCode));
    }
    // 薪酬范围
    if(StringUtils.isNotBlank(salaryCode)){
        criteria.and("salaryCode").is(salaryCode);
    }
    // 发布时间:终止日期为当前时间
    if(publishBeginDate != null){
       criteria.andOperator(Criteria.where("publishFirstDate").gte(publishBeginDate),      Criteria.where("publishFirstDate").lt(new Date()));
    }
 
    // 分组查询数据
    Aggregation aggregation = Aggregation.newAggregation(
            Aggregation.match(criteria),            //查询条件
            Aggregation.group("postId")             //分组条件
                       .first("postId").as("postId")
                       .first("top").as("top")
                       .first("publishFirstDate").as("publishFirstDate")
                       .first("orgCode").as("orgCode"),
            Aggregation.sort(new Sort(Sort.Direction.DESC,"publishFirstDate"))  // 排序
                       .and(new Sort(Sort.Direction.DESC,"publishFirstDate")),
            Aggregation.skip((queryForm.getCurrentPage() - 1) * queryForm.getPageSize()),//跳到第几个开始
            Aggregation.limit(queryForm.getPageSize())//查出多少个数据
    );
    AggregationResults<PositionSearchPo> results = 
    mongoTemplate.aggregate(aggregation,"t_position_search", PositionSearchPo.class);
    List<PositionSearchPo> list = results.getMappedResults();
 
 
    // 分组查询分组后的总记录数
    Aggregation aggregation2 = Aggregation.newAggregation(
            Aggregation.match(criteria),     //查询条件
            Aggregation.group("postId")      //分组条件
    );
    AggregationResults<PositionSearchPo> results2 = 
    mongoTemplate.aggregate(aggregation2,"t_position_search", PositionSearchPo.class);
    int dataCount = results2.getMappedResults().size();
 
    PageForm pageForm = new PageForm();
    pageForm.setCurrentPage(queryForm.getCurrentPage());
    pageForm.setPageSize(queryForm.getPageSize());
    pageForm.setDataCount(dataCount);
    pageForm.setPageData(list);
 
    return pageForm;
}
  • 返回结果与总条数
Aggregation deleted = Aggregation.newAggregation(
                match(Criteria.where("deleted").ne(true)),
                Aggregation.facet(count().as("total")).as("count")
                        .and(skip(0L),limit(2L)).as("data")
        );
        AggregationResults<HashMap> user = mongoTemplate.aggregate(deleted, "user", HashMap.class);
         System.out.println(user.getMappedResults());
        
		//设置映射
		ProjectionOperation projectionOperation = Aggregation.project().and("$records.code").as("code").
				and("$records.name").as("name").
				and("$records.ts").as("ts").
				and("$records.change_id").as("change_id").
				and("$records.create_time").as("create_time").
				and("$records.last").as("last").
				and("$records.trade_price").as("trade_price").
				and("$records.bs_flag").as("bs_flag").
				and("$records.position_before").as("position_before").
				and("$records.position_after").as("position_after").andExclude("_id");

		//筛选
		Aggregation aggregation = Aggregation.newAggregation(
				Aggregation.match(criteria),
				Aggregation.group("$change_id").push("$$ROOT").as("records").max("$create_time").as("start_time"),
				Aggregation.sort(new Sort(new Sort.Order(Sort.Direction.DESC, "start_time"))),
				Aggregation.skip(currentPage>1 ? (currentPage-1)*pageSize:0),
				Aggregation.limit(pageSize),
				Aggregation.unwind("$records"),
				projectionOperation
				);

		AggregationResults<RRoboChangeRecord> aggregate = mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(RRoboChangeRecord.class), RRoboChangeRecord.class);
		List<RRoboChangeRecord> mappedResults = aggregate.getMappedResults();

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值