参考:
聚合框架
聚合框架是MongoDB的高级查询语言,它允许我们通过转换和合并多个文档中的数据来生成新的单个文档中不存在的信息。
聚合管道操作主要包含下面几个部分:
命令 | 功能描述 |
$project | 指定输出文档里的字段. |
$match | 选择要处理的文档,与fine()类似。 |
$limit | 限制传递给下一步的文档数量。 |
$skip | 跳过一定数量的文档。 |
$unwind | 扩展数组,为每个数组入口生成一个输出文档。 |
$group | 根据key来分组文档。 |
$sort | 排序文档。 |
$geoNear | 选择某个地理位置附近的的文档。 |
$out | 把管道的结果写入某个集合。 |
$redact | 控制特定数据的访问。 |
$lookup | 多表关联(3.2版本新增) |
MongoDB查询(工具:Robo 3T):
// 两个集合关联查询
// 小表(HTQH_BROKER_CUST_RELA)做主表
db.getCollection('HTQH_BROKER_CUST_RELA').aggregate([
// 主表的查询条件
{$match: {'BROKER_NUM': {$in: ['DA1831']}}},
{
$lookup: {
// 大表(D01_CUST_LABEL)做从表
from: 'D01_CUST_LABEL',
localField: 'CUST_NUM', // 主表字段
foreignField: 'CUST_NUM', // 子表字段
as: 'BROKER_CUST' // 别名
}
},
// 关联后的查询条件
{$match: {
// 查询满足条件(LABL_GRP='sex_cd',且LABL_ID in ['1', '2'])或条件(LABL_GRP='cust_type_cd',且LABL_ID in ['100', '102'])的所有数据
$or: [
// 查询从表数据,需要用别名.从表的字段名
{$and: [{'BROKER_CUST.LABL_GRP': 'sex_cd', 'BROKER_CUST.LABL_ID': {$in: ['1', '2']}}]},
{$and: [{'BROKER_CUST.LABL_GRP': 'cust_type_cd', 'BROKER_CUST.LABL_ID': {$in: ['100', '102']}}]}
]
}},
// 查询结果只显示CUST_NUM列,_id需手动隐藏
// {$project: {CUST_NUM: 1, _id: 0}},
// 统计总条数
{$group: {_id: 'Total', count: {$sum: 1}}},
// 按CUST_NUM分组,并统计每个CUST_NUM出现的次数
// {$group: {_id: '$CUST_NUM', count: {$sum: 1}}},
]);
Java:
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver</artifactId>
<version>3.2.2</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.3.1</version>
</dependency>
<!-- 因为是jdk1.7所以用的低版本的jar -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.5.4.RELEASE</version>
</dependency>
import org.bson.Document;
import org.bson.conversions.Bson;
import com.mongodb.BasicDBObject;
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Aggregates;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Sorts;
public class demo {
// DataRow是一个HashMap
private List<String> queryCustNum(String broker_nums,
String labl_thme_id, String labl_grp_clas_id, String labl_grp,
String[] label_id, List<String> custNums) throws TKMongoException {
long beginTime = System.currentTimeMillis();
// 连接MongoDB无密码
// MongoClient client = new MongoClient("l27.0.0.1", 27017);
// MongoDatabase mongoDatabase = client.getDatabase("databaseName");
// 连接MongoDB有密码
ServerAddress serverAddress = new ServerAddress("l27.0.0.1", 27017);
List<ServerAddress> addrs = new ArrayList<>();
addrs.add(serverAddress);
// 三个参数分别为:用户名、数据库名称、密码
MongoCredential credential = MongoCredential.createScramSha1Credential("username", "databaseName", "password".toCharArray());
List<MongoCredential> credentials = new ArrayList<>();
credentials.add(credential);
// 通过连接认证获取MongoDB连接
MongoClient client = new MongoClient(addrs, credentials);
MongoDatabase mongoDatabase = client.getDatabase("databaseName");
// 联合查询条件
List<Bson> aggregationList = new LinkedList<Bson>();
// 主表查询条件
String[] brokerNumsArray = broker_nums.split(",");
aggregationList.add(Aggregates.match(Filters.in("BROKER_NUM", brokerNumsArray)));
// 从表名、主表连接字段、从表连接字段、别名
aggregationList.add(
Aggregates.lookup(CacheConstants.DOCUMENT_NAME, "CUST_NUM", "CUST_NUM", "BROKER_CUST")
);
// 从表查询条件
aggregationList.add(Aggregates.match(
Filters.and(
Filters.eq("BROKER_CUST.LABL_THME_ID", labl_thme_id),
Filters.eq("BROKER_CUST.LABL_GRP_CLAS_ID", labl_grp_clas_id),
Filters.eq("BROKER_CUST.LABL_GRP", labl_grp),
Filters.in("BROKER_CUST.LABL_ID", label_id)
)
));
if (custNums != null && custNums.size() != 0) {
aggregationList.add(Aggregates.match(
Filters.and(
Filters.in("BROKER_CUST.CUST_NUM", custNums.toArray())
)
));
}
// 只查询CUST_NUM列
BasicDBObject basicDBObject = new BasicDBObject();
basicDBObject.put("CUST_NUM", true);
basicDBObject.put("_id", false);
aggregationList.add(
Aggregates.project(basicDBObject)
);
// 从第0条开始查,查50条记录
// aggregationList.add(Aggregates.skip(0));
// aggregationList.add(Aggregates.limit(50));
AggregateIterable<Document> labelList = mongoDatabase.getCollection(CacheConstants.HTQH_BROKER_CUST_RELA).aggregate(aggregationList);
long endTime = System.currentTimeMillis();
logger.info("耗时:{}ms", endTime - beginTime);
// 打包出参
List<String> resultList = new LinkedList<String>();
for (Document dr : labelList) {
if (resultList.contains(dr.getString("CUST_NUM"))) {
continue;
}
resultList.add(dr.getString("CUST_NUM"));
}
return resultList;
}
}