MongoDB - 构造复杂查询条件执行查询

/**
 * 查询白名单详情
 *
 * @param offset        第几页开始
 * @param limit         每页显示的最大值
 * @param keyword       模糊搜索值
 * @param order         排序方式(升序/降序)
 * @param sortKey       排序的字段
 * @param threatSubType 告警类型
 * @return 白名单实体列表
 */
List<AlertWhiteEntity> findListByKeyword(
        Integer offset, Integer limit, String keyword, String order,
        String sortKey, List<String> threatSubType
);
@Override
public List<AlertWhiteEntity> findListByKeyword(
        Integer offset, Integer limit, String keyword, String order,
        String sortKey,
        List<String> threatSubType
) {
    
    
    // 开始构造查询条件
    Query query = new Query();
    // 1. 构造 keyword 的查询条件
    if (!StringUtils.isEmpty(keyword)) {
    
    
        query.addCriteria(dealKeyword(keyword));
    }
    // 2. 构造排序规则,默认是降序排序 
    Sort.Order orderSort = Sort.Order.desc(sortKey);
    if (Objects.equals(order, ASC)) {
    
    
        orderSort = Sort.Order.asc(sortKey);
    }
    // 3. 构造 threatSubType 的查询条件
    getThreatSubTypeFilter(threatSubType, query);
    // 4. 对status按照指定排序规则排序
    query.with(Sort.by(Sort.Order.desc("status"), orderSort));
    // 5. 分页查询
    query.skip((long) (offset - 1) * limit).limit(limit);
    
    // 执行查询
    return incidentMongoTemplate.find(query, AlertWhiteEntity.class);
}

1. 构造 keyword 的查询条件

private CriteriaDefinition dealKeyword(String keyword) {
    
    
    // Java的正则表达式库创建了一个正则表达式模式对象:匹配任意位置包含指定关键字的字符串,并且不区分大小写。
    Pattern pattern = Pattern.compile("^.*" + keyword + ".*$", Pattern.CASE_INSENSITIVE);
    Criteria criteria = new Criteria();
    Criteria[] criteriaArray = null;
    String fullIp = "";
    // ruleList.ruleList 中存在一个元素,该元素满足以下条件:type字段等于"srcIp"或"dstIp",value字段匹配给定的正则表达式pattern
    // creator 字段匹配给定的正则表达式pattern
    // name 字段匹配给定的正则表达式pattern
    // ruleList.ipRange 中存在一个元素,该元素的value满足以下条件: startIp字段小于等于给定的fullIp,endIp字段大于等于给定的fullIp
    if (IpUtil.judgeLegalIp(keyword)) {
    
    
        if (IpUtil.judgeIpv6(keyword)) {
    
    
            fullIp = IpUtil.formatIpv6Full(keyword);
        } else if (IpUtil.judgeIpv4(keyword)) {
    
    
            fullIp = IpUtil.formatIpv4Full(keyword);
        }
        criteriaArray = new Criteria[] {
    
    
                new Criteria().and("ruleList.ruleList").elemMatch(
                        new Criteria()
                                .andOperator(new Criteria().orOperator(new Criteria().and("type").is("srcIp"), new Criteria().and("type").is("dstIp")), new Criteria().and("value").regex(pattern))
                ),
                new Criteria().and("creator").regex(pattern),
                new Criteria().and("name").regex(pattern),
                new Criteria().and("ruleList.ipRange").elemMatch(
                        new Criteria().and("value").elemMatch(new Criteria().andOperator(Criteria.where("startIp").lte(fullIp), Criteria.where("endIp").gte(fullIp)))

                )
        };
    // 查询ruleList.ruleList中满足以下条件的元素:type字段等于"srcIp"或者"type"字段等于"dstIp",value字段匹配正则表达式pattern
    // 查询creator字段匹配正则表达式pattern的文档
    // 查询name字段匹配正则表达式pattern的文档
    } else {
    
    
        criteriaArray = new Criteria[] {
    
    
                new Criteria().and("ruleList.ruleList").elemMatch(
                        new Criteria()
                                .andOperator(new Criteria().orOperator(new Criteria().and("type").is("srcIp"), new Criteria().and("type").is("dstIp")), new Criteria().and("value").regex(pattern))
                ),
                new Criteria().and("creator").regex(pattern),
                new Criteria().and("name").regex(pattern)
        };
    }

    criteria.orOperator(criteriaArray);
    return criteria;
}

2. 构造 threatSubType 的查询条件

private void getThreatSubTypeFilter(List<String> threatSubType, Query query) {
    
    
    // 如果threatSubType不为null或者列表不为空,将“all”添加为列表,代表需要值为查询“全部”的文档
    if (threatSubType != null && threatSubType.size() != 0) {
    
    
        if (!threatSubType.contains(ALL)) {
    
    
            threatSubType.add(ALL);
        }
        // 查询threatSubTypeId在threatSubType列表中的文档
        query.addCriteria(Criteria.where("threatSubTypeId").in(threatSubType));
    }
    // 查询 deleted 为false 的文档
    query.addCriteria(Criteria.where("deleted").is(false));
}

3. 相应的实体类

@Data
@Document("t_alert_white_rules")
public class AlertWhiteEntity {
    
    
    @JsonProperty("_id")
    @MongoId
    @ApiModelProperty(value = "元api id")
    @JsonSerialize(using = ObjectIdSerializer.class)
    private ObjectId id;

    @Field("whiteId")
    @ApiModelProperty(value = "白名单id")
    private String whiteId;

    @Field("alertType")
    @ApiModelProperty(value = "告警类型,前端使用控制展示哪种模板")
    private String alertType;

    @ApiModelProperty(value = "告警类型,前端使用控制渲染告警类型")
    private String originAlertType;

    @Field("threatSubType")
    @ApiModelProperty(value = "攻击小类数量", example = "{[\"label\":\"aaaa\",\"value\":\"1_2_3\"]}")
    private List<WhiteScreenEntity> threatSubType;

    @Field("threatSubTypeView")
    @ApiModelProperty(value = "攻击小类展示数组", example = "[\"aaa\"]")
    private List<String> threatSubTypeView;

    @Field("threatSubTypeId")
    @ApiModelProperty(value = "攻击小类ID数组", example = "[\"1_2_3\"]")
    private List<String> threatSubTypeId;

    @Field("hostIp")
    @ApiModelProperty(value = "生效主机", example = "1.1.1.1")
    private List<String> hostIp;

    @Field("isHostAll")
    @ApiModelProperty(value = "是否勾选全部")
    private Boolean isHostAll;

    @Field("repeatMd5")
    @ApiModelProperty(value = "用于判断是否重复md5")
    private String repeatMd5;

    @Field("status")
    @ApiModelProperty(value = "状态", notes = "启用enable | 禁用disable")
    private String status;

    @Field("name")
    @ApiModelProperty(value = "规则名称")
    private String name;

    @Field("isUnlimited")
    @ApiModelProperty(value = "是否永久生效", notes = "永久生效1 | 自定义0")
    private Integer isUnlimited;

    @Field("sort_status")
    @ApiModelProperty(value = "分类状态", notes = "status是enable时1 | status是disable时0")
    private Integer sortStatus;

    @Field("reason")
    @ApiModelProperty(value = "备注")
    private String reason;

    @Field("ruleList")
    @ApiModelProperty(value = "规则列表")
    private RuleEntity ruleList;

    @Field("creator")
    @ApiModelProperty(value = "创建人")
    private String creator;

    @Field("creatorId")
    @ApiModelProperty(value = "创建人Id")
    private String creatorId;

    @Field("startTime")
    @ApiModelProperty(value = "开始时间")
    private Long startTime;

    @Field("endTime")
    @ApiModelProperty(value = "结束时间")
    private Long endTime;

    @Field("createTime")
    @ApiModelProperty(value = "创建时间")
    private long createTime;

    @Field("updateTime")
    @ApiModelProperty(value = "更新时间")
    private long updateTime;

    @Field("deleted")
    @ApiModelProperty(value = "是否删除", notes = "否0 | 是1")
    private boolean deleted;
}
@Data
public class RuleEntity {
    
    

    @ApiModelProperty(value = "规则列表")
    private List<RuleInfoEntity<String>> ruleList;

    @ApiModelProperty(value = "IP范围")
    private List<RuleInfoEntity<IpInfoEntity>> ipRange;

    @ApiModelProperty(value = "IOA类型")
    private List<List<RuleInfoEntity<String>>> ioaRuleList;

}
@AllArgsConstructor
@NoArgsConstructor
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiModel(description = "匹配规则")
public class RuleInfoEntity<T> implements ValidateAble {
    
    

    @ApiModelProperty(value = "匹配字段", required = true, example = "srcIp")
    private String type;

    /***
     * 该值用于处理view进行转换,不接收来自调用者
     */
    @ApiModelProperty(value = "匹配值", required = true)
    private List<T> value;

    @ApiModelProperty(value = "TMG匹配值", required = true)
    private List<T> tmgValue;

    @ApiModelProperty(value = "中文名称", example = "srcIp")
    private String title;

    @ApiModelProperty(value = "匹配模式", required = true, example = "IN")
    private String mode;

    @ApiModelProperty(value = "匹配值")
    private List<String> view;

    @ApiModelProperty(value = "是否忽略大小写")
    private Boolean isIgnorecase;
}
@Data
public class IpInfoEntity {
    
    

    @ApiModelProperty(value = "开始IP")
    private String startIp;

    @ApiModelProperty(value = "结束ip")
    private String endIp;

}

猜你喜欢

转载自blog.csdn.net/qq_42764468/article/details/132562141