Java mongoDB查询(Query Criteria)

MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
在这里插入图片描述

Query

//添加过滤条件
public Query addCriteria(CriteriaDefinition criteriaDefinition) {
    CriteriaDefinition existing = (CriteriaDefinition)this.criteria.get(criteriaDefinition.getKey());
    String key = criteriaDefinition.getKey();
    if (existing == null) {
        this.criteria.put(key, criteriaDefinition);
        return this;
    } else {
        throw new InvalidMongoDbApiUsageException(String.format("Due to limitations of the com.mongodb.BasicDocument, you can't add a second '%s' criteria. Query already contains '%s'", key, SerializationUtils.serializeToJsonSafely(existing.getCriteriaObject())));
    }
}

//指定返回字段
public Field fields() {
    if (this.fieldSpec == null) {
        this.fieldSpec = new Field();
    }

    return this.fieldSpec;
}

//跳过指定数量的数据
public Query skip(long skip) {
    this.skip = skip;
    return this;
}

//接受一个数字参数
public Query limit(int limit) {
    this.limit = limit;
    return this;
}

//
public Query withHint(String name) {
    Assert.hasText(name, "Hint must not be empty or null!");
    this.hint = name;
    return this;
}

//分页查询
public Query with(Pageable pageable) {
    if (pageable.isUnpaged()) {
        return this;
    } else {
        this.limit = pageable.getPageSize();
        this.skip = pageable.getOffset();
        return this.with(pageable.getSort());
    }
}

//排序
public Query with(Sort sort) {
    Assert.notNull(sort, "Sort must not be null!");
    if (sort.isUnsorted()) {
        return this;
    } else {
        sort.stream().filter(Order::isIgnoreCase).findFirst().ifPresent((it) -> {
            throw new IllegalArgumentException(String.format("Given sort contained an Order for %s with ignore case! MongoDB does not support sorting ignoring case currently!", it.getProperty()));
        });
        this.sort = this.sort.and(sort);
        return this;
    }
}

public Set<Class<?>> getRestrictedTypes() {
    return this.restrictedTypes;
}

public Query restrict(Class<?> type, Class<?>... additionalTypes) {
    Assert.notNull(type, "Type must not be null!");
    Assert.notNull(additionalTypes, "AdditionalTypes must not be null");
    this.restrictedTypes.add(type);
    this.restrictedTypes.addAll(Arrays.asList(additionalTypes));
    return this;
}

//对文档的操作
public Document getQueryObject() {
    Document document = new Document();
    Iterator var2 = this.criteria.values().iterator();

    while(var2.hasNext()) {
        CriteriaDefinition definition = (CriteriaDefinition)var2.next();
        document.putAll(definition.getCriteriaObject());
    }

    if (!this.restrictedTypes.isEmpty()) {
        document.put("_$RESTRICTED_TYPES", this.getRestrictedTypes());
    }

    return document;
}

//对文档的操作
public Document getFieldsObject() {
    return this.fieldSpec == null ? new Document() : this.fieldSpec.getFieldsObject();
}

//对文档的操作
public Document getSortObject() {
    if (this.sort.isUnsorted()) {
        return new Document();
    } else {
        Document document = new Document();
        this.sort.stream().forEach((order) -> {
            document.put(order.getProperty(), order.isAscending() ? 1 : -1);
        });
        return document;
    }
}

//指定在光标上进行处理操作的累积时间限制(以毫秒为单位)。
public Query maxTimeMsec(long maxTimeMsec) {
    this.meta.setMaxTimeMsec(maxTimeMsec);
    return this;
}

Criteria

    /**
     *Query query = new Query();
     * query.addCriteria(Criteria.where("name").is(name));
     * @param key
     * @return
     */
    //把多个条件组合在一起
        public static Criteria where(String key) {
            return new Criteria(key);
        }

        //封装查询条件
        /**例如:
         *
         *创建匹配器,即如何使用查询条件
         * ExampleMatcher matcher = ExampleMatcher.matching() //构建对象
         *        .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) //改变默认字符串匹配方式:模糊查询
         *        .withIgnoreCase(true) //改变默认大小写忽略方式:忽略大小写
         *        .withMatcher("name", ExampleMatcher.GenericPropertyMatchers.contains()) //标题采用“包含匹配”的方式查询
         *        .withIgnorePaths("pageNum", "pageSize");  //忽略属性,不参与查询
         *创建实例
         *Example<Student> example = Example.of(student, matcher);
         *Query query = new Query(Criteria.byExample(example));
         **/
        public static Criteria byExample(Object example) {
            return byExample(Example.of(example));
        }


        //封装查询条件
        public static Criteria byExample(Example<?> example) {
            return (new Criteria()).alike(example);
        }

        //匹配文档
        public static Criteria matchingDocumentStructure(MongoJsonSchema schema) {
            return (new Criteria()).andDocumentStructureMatches(schema);
        }

        //并且
        public Criteria and(String key) {
            return new Criteria(this.criteriaChain, key);
        }

        //是
        public Criteria is(@Nullable Object o) {
            if (!this.isValue.equals(NOT_SET)) {
                throw new InvalidMongoDbApiUsageException("Multiple 'is' values declared. You need to use 'and' with multiple criteria");
            } else if (this.lastOperatorWasNot()) {
                throw new InvalidMongoDbApiUsageException("Invalid query: 'not' can't be used with 'is' - use 'ne' instead.");
            } else {
                this.isValue = o;
                return this;
            }
        }

        //用于匹配正则表达式
        private boolean lastOperatorWasNot() {
            return !this.criteria.isEmpty() && "$not".equals(this.criteria.keySet().toArray()[this.criteria.size() - 1]);
        }

        //不等于
        public Criteria ne(@Nullable Object o) {
            this.criteria.put("$ne", o);
            return this;
        }

        //小于
        public Criteria lt(Object o) {
            this.criteria.put("$lt", o);
            return this;
        }

        //小于等于
        public Criteria lte(Object o) {
            this.criteria.put("$lte", o);
            return this;
        }

        //大于
        public Criteria gt(Object o) {
            this.criteria.put("$gt", o);
            return this;
        }

        //大于等于
        public Criteria gte(Object o) {
            this.criteria.put("$gte", o);
            return this;
        }

        //包含
        public Criteria in(Object... o) {
            if (o.length > 1 && o[1] instanceof Collection) {
                throw new InvalidMongoDbApiUsageException("You can only pass in one argument of type " + o[1].getClass().getName());
            } else {
                this.criteria.put("$in", Arrays.asList(o));
                return this;
            }
        }

        //包含
        public Criteria in(Collection<?> c) {
            this.criteria.put("$in", c);
            return this;
        }

        //与in相反
        public Criteria nin(Object... o) {
            return this.nin((Collection)Arrays.asList(o));
        }

        //与in相反
        public Criteria nin(Collection<?> o) {
            this.criteria.put("$nin", o);
            return this;
        }

        //取模(求余)运算 ,即:key对应的值%value==remainder(求余是否等于remainder)
        public Criteria mod(Number value, Number remainder) {
            List<Object> l = new ArrayList();
            l.add(value);
            l.add(remainder);
            this.criteria.put("$mod", l);
            return this;
        }

        //key键对应的集合包含col(all是包含关系,in是被包含关系)
        public Criteria all(Object... o) {
            return this.all((Collection)Arrays.asList(o));
        }

        public Criteria all(Collection<?> o) {
            this.criteria.put("$all", o);
            return this;
        }

        //匹配key所对应的集合的元素的指定数量(!!!不能进行像<5之类的范围匹配)
        public Criteria size(int s) {
            this.criteria.put("$size", s);
            return this;
        }

        //查询字段是否存在(true:存在,false:不存在)
        public Criteria exists(boolean b) {
            this.criteria.put("$exists", b);
            return this;
        }

        //基于 bson type来匹配一个元素的类型,像是按照类型ID来匹配
        public Criteria type(int t) {
            this.criteria.put("$type", t);
            return this;
        }

        public Criteria type(Type... types) {
            Assert.notNull(types, "Types must not be null!");
            Assert.noNullElements(types, "Types must not contain null.");
            this.criteria.put("$type", Arrays.asList(types).stream().map(Type::value).collect(Collectors.toList()));
            return this;
        }

        //取反
        public Criteria not() {
            return this.not((Object)null);
        }

        private Criteria not(@Nullable Object value) {
            this.criteria.put("$not", value);
            return this;
        }

        //模糊查询用
        public Criteria regex(String re) {
            return this.regex(re, (String)null);
        }

        public Criteria regex(String re, @Nullable String options) {
            return this.regex(this.toPattern(re, options));
        }

        public Criteria regex(Pattern pattern) {
            Assert.notNull(pattern, "Pattern must not be null!");
            if (this.lastOperatorWasNot()) {
                return this.not(pattern);
            } else {
                this.isValue = pattern;
                return this;
            }
        }

        public Criteria regex(BsonRegularExpression regex) {
            if (this.lastOperatorWasNot()) {
                return this.not(regex);
            } else {
                this.isValue = regex;
                return this;
            }
        }

        //
        private Pattern toPattern(String regex, @Nullable String options) {
            Assert.notNull(regex, "Regex string must not be null!");
            return Pattern.compile(regex, options == null ? 0 : BSON.regexFlags(options));
        }

        public Criteria withinSphere(Circle circle) {
            Assert.notNull(circle, "Circle must not be null!");
            this.criteria.put("$geoWithin", new GeoCommand(new Sphere(circle)));
            return this;
        }

        public Criteria within(Shape shape) {
            Assert.notNull(shape, "Shape must not be null!");
            this.criteria.put("$geoWithin", new GeoCommand(shape));
            return this;
        }

        //输出接近某一地理位置的有序文档
        public Criteria near(Point point) {
            Assert.notNull(point, "Point must not be null!");
            this.criteria.put("$near", point);
            return this;
        }

        //指定地理空间查询从最近到最远返回文档的点。 MongoDB 使用球面几何计算$nearSphere的距离
        public Criteria nearSphere(Point point) {
            Assert.notNull(point, "Point must not be null!");
            this.criteria.put("$nearSphere", point);
            return this;
        }

        //
        public Criteria intersects(GeoJson geoJson) {
            Assert.notNull(geoJson, "GeoJson must not be null!");
            this.criteria.put("$geoIntersects", geoJson);
            return this;
        }

        //创建一个地理空间标准,与nearSphere一起使用
        public Criteria maxDistance(double maxDistance) {
            if (!this.createNearCriteriaForCommand("$near", "$maxDistance", maxDistance) && !this.createNearCriteriaForCommand("$nearSphere", "$maxDistance", maxDistance)) {
                this.criteria.put("$maxDistance", maxDistance);
                return this;
            } else {
                return this;
            }
        }

        //mongodb地理空间计算逻辑
        public Criteria minDistance(double minDistance) {
            if (!this.createNearCriteriaForCommand("$near", "$minDistance", minDistance) && !this.createNearCriteriaForCommand("$nearSphere", "$minDistance", minDistance)) {
                this.criteria.put("$minDistance", minDistance);
                return this;
            } else {
                return this;
            }
        }

        //匹配查询
        public Criteria elemMatch(Criteria c) {
            this.criteria.put("$elemMatch", c.getCriteriaObject());
            return this;
        }

        //使用给定对象作为模式创建条件
        public Criteria alike(Example<?> sample) {
            this.criteria.put("$example", sample);
            this.criteriaChain.add(this);
            return this;
        }

        //创建一个criteria ($jsonSchema),根据MongoJsonSchema定义的给定结构匹配文档
        public Criteria andDocumentStructureMatches(MongoJsonSchema schema) {
            Assert.notNull(schema, "Schema must not be null!");
            Criteria schemaCriteria = new Criteria();
            schemaCriteria.criteria.putAll(schema.toDocument());
            return this.registerCriteriaChainElement(schemaCriteria);
        }

        public Criteria.BitwiseCriteriaOperators bits() {
            return new Criteria.BitwiseCriteriaOperatorsImpl(this);
        }

        //或者

        /**
         * Aggregation agg = Aggregation.newAggregation(
         *     Aggregation.match(new Criteria()
         *             .andOperator(Criteria.where("onlineTime").gt(new Date()))
         *             .orOperator( Criteria.where("offlineTime").gt(new Date())
         *     ,Criteria.where("offlineTime").exists(false) ))
         * @param criteria
         * @return
         */
        public Criteria orOperator(Criteria... criteria) {
            BasicDBList bsonList = this.createCriteriaList(criteria);
            return this.registerCriteriaChainElement((new Criteria("$or")).is(bsonList));
        }

        //非或者
        public Criteria norOperator(Criteria... criteria) {
            BasicDBList bsonList = this.createCriteriaList(criteria);
            return this.registerCriteriaChainElement((new Criteria("$nor")).is(bsonList));
        }

        //并且
        public Criteria andOperator(Criteria... criteria) {
            BasicDBList bsonList = this.createCriteriaList(criteria);
            return this.registerCriteriaChainElement((new Criteria("$and")).is(bsonList));
        }

        private Criteria registerCriteriaChainElement(Criteria criteria) {
            if (this.lastOperatorWasNot()) {
                throw new IllegalArgumentException("operator $not is not allowed around criteria chain element: " + criteria.getCriteriaObject());
            } else {
                this.criteriaChain.add(criteria);
                return this;
            }
        }

        @Nullable
        public String getKey() {
            return this.key;
        }

        public Document getCriteriaObject() {
            if (this.criteriaChain.size() == 1) {
                return ((Criteria)this.criteriaChain.get(0)).getSingleCriteriaObject();
            } else if (CollectionUtils.isEmpty(this.criteriaChain) && !CollectionUtils.isEmpty(this.criteria)) {
                return this.getSingleCriteriaObject();
            } else {
                Document criteriaObject = new Document();
                Iterator var2 = this.criteriaChain.iterator();

                while(var2.hasNext()) {
                    Criteria c = (Criteria)var2.next();
                    Document document = c.getSingleCriteriaObject();
                    Iterator var5 = document.keySet().iterator();

                    while(var5.hasNext()) {
                        String k = (String)var5.next();
                        this.setValue(criteriaObject, k, document.get(k));
                    }
                }

                return criteriaObject;
            }
        }

        protected Document getSingleCriteriaObject() {
            Document document = new Document();
            boolean not = false;
            Iterator var3 = this.criteria.entrySet().iterator();

            while(true) {
                while(var3.hasNext()) {
                    Entry<String, Object> entry = (Entry)var3.next();
                    String key = (String)entry.getKey();
                    Object value = entry.getValue();
                    if (requiresGeoJsonFormat(value)) {
                        value = new Document("$geometry", value);
                    }

                    if (not) {
                        Document notDocument = new Document();
                        notDocument.put(key, value);
                        document.put("$not", notDocument);
                        not = false;
                    } else if ("$not".equals(key) && value == null) {
                        not = true;
                    } else {
                        document.put(key, value);
                    }
                }

                if (!StringUtils.hasText(this.key)) {
                    if (not) {
                        return new Document("$not", document);
                    }

                    return document;
                }

                Document queryCriteria = new Document();
                if (!NOT_SET.equals(this.isValue)) {
                    queryCriteria.put(this.key, this.isValue);
                    queryCriteria.putAll(document);
                } else {
                    queryCriteria.put(this.key, document);
                }

                return queryCriteria;
            }
        }

        private BasicDBList createCriteriaList(Criteria[] criteria) {
            BasicDBList bsonList = new BasicDBList();
            Criteria[] var3 = criteria;
            int var4 = criteria.length;

            for(int var5 = 0; var5 < var4; ++var5) {
                Criteria c = var3[var5];
                bsonList.add(c.getCriteriaObject());
            }

            return bsonList;
        }

        private void setValue(Document document, String key, Object value) {
            Object existing = document.get(key);
            if (existing == null) {
                document.put(key, value);
            } else {
                throw new InvalidMongoDbApiUsageException("Due to limitations of the com.mongodb.BasicDocument, you can't add a second '" + key + "' expression specified as '" + key + " : " + value + "'. Criteria already contains '" + key + " : " + existing + "'.");
            }
        }

        private boolean createNearCriteriaForCommand(String command, String operation, double maxDistance) {
            if (!this.criteria.containsKey(command)) {
                return false;
            } else {
                Object existingNearOperationValue = this.criteria.get(command);
                if (existingNearOperationValue instanceof Document) {
                    ((Document)existingNearOperationValue).put(operation, maxDistance);
                    return true;
                } else if (existingNearOperationValue instanceof GeoJson) {
                    Document dbo = (new Document("$geometry", existingNearOperationValue)).append(operation, maxDistance);
                    this.criteria.put(command, dbo);
                    return true;
                } else {
                    return false;
                }
            }
        }

        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            } else if (obj != null && this.getClass().equals(obj.getClass())) {
                Criteria that = (Criteria)obj;
                if (this.criteriaChain.size() != that.criteriaChain.size()) {
                    return false;
                } else {
                    for(int i = 0; i < this.criteriaChain.size(); ++i) {
                        Criteria left = (Criteria)this.criteriaChain.get(i);
                        Criteria right = (Criteria)that.criteriaChain.get(i);
                        if (!this.simpleCriteriaEquals(left, right)) {
                            return false;
                        }
                    }

                    return true;
                }
            } else {
                return false;
            }
        }

        private boolean simpleCriteriaEquals(Criteria left, Criteria right) {
            boolean keyEqual = left.key == null ? right.key == null : left.key.equals(right.key);
            boolean criteriaEqual = left.criteria.equals(right.criteria);
            boolean valueEqual = this.isEqual(left.isValue, right.isValue);
            return keyEqual && criteriaEqual && valueEqual;
        }

        //判断是否相等
        private boolean isEqual(Object left, Object right) {
            if (left == null) {
                return right == null;
            } else if (Pattern.class.isInstance(left)) {
                if (!Pattern.class.isInstance(right)) {
                    return false;
                } else {
                    Pattern leftPattern = (Pattern)left;
                    Pattern rightPattern = (Pattern)right;
                    return leftPattern.pattern().equals(rightPattern.pattern()) && leftPattern.flags() == rightPattern.flags();
                }
            } else {
                return ObjectUtils.nullSafeEquals(left, right);
            }
        }

        public int hashCode() {
            int result = 17;
            int result = result + ObjectUtils.nullSafeHashCode(this.key);
            result += this.criteria.hashCode();
            result += ObjectUtils.nullSafeHashCode(this.isValue);
            return result;
        }

        private static boolean requiresGeoJsonFormat(Object value) {
            return value instanceof GeoJson || value instanceof GeoCommand && ((GeoCommand)value).getShape() instanceof GeoJson;
        }

        private static class BitwiseCriteriaOperatorsImpl implements Criteria.BitwiseCriteriaOperators {
            private final Criteria target;

            BitwiseCriteriaOperatorsImpl(Criteria target) {
                this.target = target;
            }

            public Criteria allClear(int numericBitmask) {
                return this.numericBitmask("$bitsAllClear", numericBitmask);
            }

            public Criteria allClear(String bitmask) {
                return this.stringBitmask("$bitsAllClear", bitmask);
            }

            public Criteria allClear(List<Integer> positions) {
                return this.positions("$bitsAllClear", positions);
            }

            public Criteria allSet(int numericBitmask) {
                return this.numericBitmask("$bitsAllSet", numericBitmask);
            }

            public Criteria allSet(String bitmask) {
                return this.stringBitmask("$bitsAllSet", bitmask);
            }

            public Criteria allSet(List<Integer> positions) {
                return this.positions("$bitsAllSet", positions);
            }

            public Criteria anyClear(int numericBitmask) {
                return this.numericBitmask("$bitsAnyClear", numericBitmask);
            }

            public Criteria anyClear(String bitmask) {
                return this.stringBitmask("$bitsAnyClear", bitmask);
            }

            public Criteria anyClear(List<Integer> positions) {
                return this.positions("$bitsAnyClear", positions);
            }

            public Criteria anySet(int numericBitmask) {
                return this.numericBitmask("$bitsAnySet", numericBitmask);
            }

            public Criteria anySet(String bitmask) {
                return this.stringBitmask("$bitsAnySet", bitmask);
            }

            public Criteria anySet(List<Integer> positions) {
                return this.positions("$bitsAnySet", positions);
            }

            private Criteria positions(String operator, List<Integer> positions) {
                Assert.notNull(positions, "Positions must not be null!");
                Assert.noNullElements(positions.toArray(), "Positions must not contain null values.");
                this.target.criteria.put(operator, positions);
                return this.target;
            }

            private Criteria stringBitmask(String operator, String bitmask) {
                Assert.hasText(bitmask, "Bitmask must not be null!");
                this.target.criteria.put(operator, new Binary(Base64Utils.decodeFromString(bitmask)));
                return this.target;
            }

            private Criteria numericBitmask(String operator, int bitmask) {
                this.target.criteria.put(operator, bitmask);
                return this.target;
            }
        }

        public interface BitwiseCriteriaOperators {
            Criteria allClear(int var1);

            Criteria allClear(String var1);

            Criteria allClear(List<Integer> var1);

            Criteria allSet(int var1);

            Criteria allSet(String var1);

            Criteria allSet(List<Integer> var1);

            Criteria anyClear(int var1);

            Criteria anyClear(String var1);

            Criteria anyClear(List<Integer> var1);

            Criteria anySet(int var1);

            Criteria anySet(String var1);

            Criteria anySet(List<Integer> var1);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值