|
|
@@ -0,0 +1,574 @@
|
|
|
+package com.uas.kanban.base;
|
|
|
+
|
|
|
+import java.lang.reflect.Field;
|
|
|
+import java.lang.reflect.Modifier;
|
|
|
+import java.lang.reflect.ParameterizedType;
|
|
|
+import java.lang.reflect.Type;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Collection;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Map.Entry;
|
|
|
+import java.util.Set;
|
|
|
+
|
|
|
+import org.bson.types.ObjectId;
|
|
|
+import org.mongodb.morphia.Datastore;
|
|
|
+import org.mongodb.morphia.Key;
|
|
|
+import org.mongodb.morphia.annotations.Embedded;
|
|
|
+import org.mongodb.morphia.annotations.Reference;
|
|
|
+import org.mongodb.morphia.query.FindOptions;
|
|
|
+import org.mongodb.morphia.query.MorphiaIterator;
|
|
|
+import org.mongodb.morphia.query.Query;
|
|
|
+import org.mongodb.morphia.query.UpdateOperations;
|
|
|
+import org.mongodb.morphia.query.UpdateResults;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.mongodb.DBCollection;
|
|
|
+import com.mongodb.WriteResult;
|
|
|
+import com.uas.kanban.annotation.FieldProperty;
|
|
|
+import com.uas.kanban.annotation.NotEmpty;
|
|
|
+import com.uas.kanban.exception.OperationException;
|
|
|
+import com.uas.kanban.util.ArrayUtils;
|
|
|
+import com.uas.kanban.util.CollectionUtils;
|
|
|
+import com.uas.kanban.util.ObjectUtils;
|
|
|
+import com.uas.kanban.util.StringUtils;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 基本Dao操作
|
|
|
+ *
|
|
|
+ * @author sunyj
|
|
|
+ * @since 2017年8月29日 上午10:06:32
|
|
|
+ */
|
|
|
+public class BaseDao<T extends BaseEntity> {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ protected Datastore datastore;
|
|
|
+
|
|
|
+ private Class<T> entityClass;
|
|
|
+
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ protected BaseDao() throws IllegalStateException {
|
|
|
+ Class<?> clazz = this.getClass();
|
|
|
+ Type genericSuperclass = clazz.getGenericSuperclass();
|
|
|
+ if (!(genericSuperclass instanceof ParameterizedType)) {
|
|
|
+ // 如果子类继承时未指定<T>的类型
|
|
|
+ throw new IllegalStateException("泛型类型解析错误");
|
|
|
+ }
|
|
|
+ Type[] actualTypeArguments = ((ParameterizedType) genericSuperclass).getActualTypeArguments();
|
|
|
+ if (ArrayUtils.isEmpty(actualTypeArguments)) {
|
|
|
+ throw new IllegalStateException("泛型类型解析错误");
|
|
|
+ }
|
|
|
+ entityClass = (Class<T>) actualTypeArguments[0];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Returns a new query bound to the collection (a specific
|
|
|
+ * {@link DBCollection})
|
|
|
+ *
|
|
|
+ * @return the query
|
|
|
+ */
|
|
|
+ public Query<T> createQuery() {
|
|
|
+ return datastore.createQuery(entityClass);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Returns a new query bound to the collection (a specific
|
|
|
+ * {@link DBCollection})
|
|
|
+ *
|
|
|
+ * @param code
|
|
|
+ * the code to query
|
|
|
+ * @return the query
|
|
|
+ */
|
|
|
+ public Query<T> createQuery(@NotEmpty("code") String code) {
|
|
|
+ return createQuery().field("code").equal(code);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * The builder for all update operations
|
|
|
+ *
|
|
|
+ * @return the new UpdateOperations instance
|
|
|
+ */
|
|
|
+ public UpdateOperations<T> createUpdateOperations() {
|
|
|
+ return datastore.createUpdateOperations(entityClass);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * The builder for all update operations (by the entity)
|
|
|
+ *
|
|
|
+ * @param t
|
|
|
+ * the entity to update
|
|
|
+ * @return the new UpdateOperations instance
|
|
|
+ */
|
|
|
+ public UpdateOperations<T> createUpdateOperations(@NotEmpty("t") T t) {
|
|
|
+ return createUpdateOperations(t, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * The builder for all update operations (by the entity)
|
|
|
+ *
|
|
|
+ * @param t
|
|
|
+ * the entity to update
|
|
|
+ * @param ignoreFields
|
|
|
+ * 不更新的字段
|
|
|
+ * @return the new UpdateOperations instance
|
|
|
+ */
|
|
|
+ public UpdateOperations<T> createUpdateOperations(@NotEmpty("t") T t, Set<String> ignoreFields) {
|
|
|
+ UpdateOperations<T> operations = createUpdateOperations();
|
|
|
+ Field[] declaredFields = entityClass.getDeclaredFields();
|
|
|
+ // 通过反射遍历对象的成员变量,自动构造UpdateOperations
|
|
|
+ for (Field field : declaredFields) {
|
|
|
+ String name = field.getName();
|
|
|
+ // 不更新 ignoreFields 中指定的字段
|
|
|
+ if (!CollectionUtils.isEmpty(ignoreFields) && ignoreFields.contains(name)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ Object value = null;
|
|
|
+ int modifiers = field.getModifiers();
|
|
|
+ // 不处理static或final修饰的变量(只处理普通成员变量)
|
|
|
+ if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ if (!field.isAccessible()) {
|
|
|
+ field.setAccessible(true);
|
|
|
+ value = field.get(t);
|
|
|
+ field.setAccessible(false);
|
|
|
+ } else {
|
|
|
+ value = field.get(t);
|
|
|
+ }
|
|
|
+ } catch (IllegalArgumentException | IllegalAccessException e) {
|
|
|
+ throw new IllegalStateException("通过反射自动构造 UpdateOperations 时出错", e);
|
|
|
+ }
|
|
|
+ // 如果值为空,则移除文档中的该字段
|
|
|
+ if (ObjectUtils.isEmpty(value)) {
|
|
|
+ operations.unset(name);
|
|
|
+ } else {
|
|
|
+ operations.set(name, value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return operations;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Saves an entity (Object) and updates the @Id field
|
|
|
+ *
|
|
|
+ * @param t
|
|
|
+ * the entity to save
|
|
|
+ * @return the entity saved
|
|
|
+ * @throws IllegalArgumentException
|
|
|
+ * @throws IllegalStateException
|
|
|
+ */
|
|
|
+ public T save(@NotEmpty("t") T t) throws IllegalArgumentException, IllegalStateException {
|
|
|
+ if (!StringUtils.isEmpty(t.getCode())) {
|
|
|
+ throw new IllegalArgumentException("不能指定 code:" + t);
|
|
|
+ }
|
|
|
+ checkField(t);
|
|
|
+ t.init();
|
|
|
+ Key<T> key = datastore.save(t);
|
|
|
+ Object id = key.getId();
|
|
|
+ if (id == null || !(id instanceof ObjectId)) {
|
|
|
+ throw new IllegalStateException("保存数据出错:id 不存在或者并非 ObjectId 类型");
|
|
|
+ }
|
|
|
+ return t;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 对对象的字段进行检查,包括是否为空等
|
|
|
+ *
|
|
|
+ * @param <K>
|
|
|
+ * 要检查的对象的类型,可与 {@link T} 不同
|
|
|
+ *
|
|
|
+ * @param k
|
|
|
+ * 要检查的对象
|
|
|
+ * @throws IllegalArgumentException
|
|
|
+ * @throws IllegalStateException
|
|
|
+ */
|
|
|
+ public <K> void checkField(@NotEmpty("k") K k) throws IllegalArgumentException, IllegalStateException {
|
|
|
+ Class<? extends Object> clazz = k.getClass();
|
|
|
+ Field[] declaredFields = clazz.getDeclaredFields();
|
|
|
+ for (Field field : declaredFields) {
|
|
|
+ int modifiers = field.getModifiers();
|
|
|
+ // 不处理static修饰的变量
|
|
|
+ if (Modifier.isStatic(modifiers)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ Embedded embedded = field.getAnnotation(Embedded.class);
|
|
|
+ Reference reference = field.getAnnotation(Reference.class);
|
|
|
+ FieldProperty fieldProperty = field.getAnnotation(FieldProperty.class);
|
|
|
+ // 只有使用 {@link FieldProperty} 指定不可为空,或者是嵌入或引用对象,才处理
|
|
|
+ if ((fieldProperty == null || fieldProperty.nullable()) && embedded == null && reference == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ Object value = null;
|
|
|
+ try {
|
|
|
+ if (!field.isAccessible()) {
|
|
|
+ field.setAccessible(true);
|
|
|
+ value = field.get(k);
|
|
|
+ field.setAccessible(false);
|
|
|
+ } else {
|
|
|
+ value = field.get(k);
|
|
|
+ }
|
|
|
+ } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
|
|
|
+ throw new IllegalStateException("通过反射检查字段是否为空时出错", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果使用 {@link FieldProperty} 指定不可为空,但是值为空,则抛出异常
|
|
|
+ if (fieldProperty != null && !fieldProperty.nullable() && ObjectUtils.isEmpty(value)) {
|
|
|
+ throw new IllegalArgumentException("字段为空:" + clazz.getName() + "." + field.getName() + " = " + value);
|
|
|
+ }
|
|
|
+ // 如果是嵌入或引用对象,并且不为空,则递归检测
|
|
|
+ if ((embedded != null || reference != null) && !ObjectUtils.isEmpty(value)) {
|
|
|
+ // 如果是Collection
|
|
|
+ if (value instanceof Collection) {
|
|
|
+ Collection<?> colletion = (Collection<?>) value;
|
|
|
+ for (Object obj : colletion) {
|
|
|
+ checkField(obj);
|
|
|
+ }
|
|
|
+ } else if (value instanceof Map) {
|
|
|
+ Map<?, ?> map = (Map<?, ?>) value;
|
|
|
+ for (Object key : map.keySet()) {
|
|
|
+ checkField(key);
|
|
|
+ }
|
|
|
+ for (Object v : map.values()) {
|
|
|
+ checkField(v);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ checkField(value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除所有数据
|
|
|
+ *
|
|
|
+ * @return results of the delete
|
|
|
+ */
|
|
|
+ public int deleteAll() {
|
|
|
+ Query<T> query = createQuery();
|
|
|
+ return delete(query);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Delete the given entity (by code)
|
|
|
+ *
|
|
|
+ * @param code
|
|
|
+ * the code to delete
|
|
|
+ * @return results of the delete
|
|
|
+ */
|
|
|
+ public int deleteOne(@NotEmpty("code") String code) {
|
|
|
+ Query<T> query = createQuery(code);
|
|
|
+ return delete(query);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据指定的条件删除数据
|
|
|
+ *
|
|
|
+ * @param filters
|
|
|
+ * 过滤条件,key-value的形式
|
|
|
+ * @return results of the delete
|
|
|
+ */
|
|
|
+ public int delete(@NotEmpty("filters") Map<String, Object> filters) {
|
|
|
+ Query<T> query = createQuery();
|
|
|
+ filter(query, filters);
|
|
|
+ return delete(query);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Deletes entities based on the query
|
|
|
+ *
|
|
|
+ * @param query
|
|
|
+ * the query used to match the documents to update
|
|
|
+ * @return results of the delete
|
|
|
+ */
|
|
|
+ public int delete(@NotEmpty("query") Query<T> query) {
|
|
|
+ WriteResult writeResult = datastore.delete(query);
|
|
|
+ return writeResult.getN();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Update the given entity (by code)
|
|
|
+ *
|
|
|
+ * @param t
|
|
|
+ * the entity to update
|
|
|
+ * @return the entity updated
|
|
|
+ * @throws OperationException
|
|
|
+ * @throws IllegalArgumentException
|
|
|
+ */
|
|
|
+ public int update(@NotEmpty("t") T t) throws IllegalArgumentException, OperationException {
|
|
|
+ return update(t, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Update the given entity (by code)
|
|
|
+ *
|
|
|
+ * @param t
|
|
|
+ * the entity to update
|
|
|
+ * @param ignoreFields
|
|
|
+ * 不更新的字段
|
|
|
+ * @return the entity updated
|
|
|
+ * @throws OperationException
|
|
|
+ * @throws IllegalArgumentException
|
|
|
+ */
|
|
|
+ public int update(@NotEmpty("t") T t, Set<String> ignoreFields)
|
|
|
+ throws IllegalArgumentException, OperationException {
|
|
|
+ String code = t.getCode();
|
|
|
+ if (StringUtils.isEmpty(code)) {
|
|
|
+ throw new IllegalArgumentException("没有指定 code:" + t);
|
|
|
+ }
|
|
|
+ checkField(t);
|
|
|
+ UpdateOperations<T> operations = createUpdateOperations(t, ignoreFields);
|
|
|
+ return update(code, operations);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Update the given entity (by code)
|
|
|
+ *
|
|
|
+ * @param code
|
|
|
+ * the code to update
|
|
|
+ * @return number updated
|
|
|
+ */
|
|
|
+ public int update(@NotEmpty("code") String code, @NotEmpty("operations") UpdateOperations<T> operations) {
|
|
|
+ Query<T> query = createQuery(code);
|
|
|
+ return update(query, operations);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Updates all entities found with the operations; this is an atomic
|
|
|
+ * operation per entity
|
|
|
+ *
|
|
|
+ * @param query
|
|
|
+ * the query used to match the documents to update
|
|
|
+ * @param operations
|
|
|
+ * the update operations to perform
|
|
|
+ * @return number updated
|
|
|
+ */
|
|
|
+ private int update(@NotEmpty("query") Query<T> query, @NotEmpty("operations") UpdateOperations<T> operations) {
|
|
|
+ operations.set("lastModified", new Date());
|
|
|
+ operations.inc("version");
|
|
|
+ UpdateResults updateResults = datastore.update(query, operations);
|
|
|
+ return updateResults.getUpdatedCount();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Find all instances
|
|
|
+ *
|
|
|
+ * @return The results
|
|
|
+ */
|
|
|
+ public List<T> findAll() {
|
|
|
+ Query<T> query = createQuery();
|
|
|
+ return find(query);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Find the given entity (by code); shorthand for
|
|
|
+ * {@code find("code ", code)}
|
|
|
+ *
|
|
|
+ * @param code
|
|
|
+ * the code to query
|
|
|
+ * @return the matched entity. may be null.
|
|
|
+ */
|
|
|
+ public T findOne(@NotEmpty("code") String code) {
|
|
|
+ return createQuery(code).get();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Find the given entities (by code);
|
|
|
+ *
|
|
|
+ * @param codes
|
|
|
+ * the codes to query
|
|
|
+ * @return the matched entities. may be null.
|
|
|
+ */
|
|
|
+ public List<T> findIn(@NotEmpty("codes") Iterable<String> codes) {
|
|
|
+ return createQuery().field("code").in(codes).asList();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据指定的条件查询数据
|
|
|
+ *
|
|
|
+ * @param filters
|
|
|
+ * 过滤条件,key-value的形式
|
|
|
+ * @return The results
|
|
|
+ */
|
|
|
+ public List<T> find(@NotEmpty("filters") Map<String, Object> filters) {
|
|
|
+ Query<T> query = createQuery();
|
|
|
+ filter(query, filters);
|
|
|
+ return find(query);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Execute the query and get the results
|
|
|
+ *
|
|
|
+ * @param query
|
|
|
+ * the query used to match the documents to update
|
|
|
+ * @return The results
|
|
|
+ */
|
|
|
+ public List<T> find(@NotEmpty("query") Query<T> query) {
|
|
|
+ List<T> result = new ArrayList<>();
|
|
|
+ MorphiaIterator<T, T> morphiaIterator = query.fetch();
|
|
|
+ while (morphiaIterator.hasNext()) {
|
|
|
+ result.add(morphiaIterator.next());
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分页获取数据
|
|
|
+ *
|
|
|
+ * @param page
|
|
|
+ * 页码
|
|
|
+ * @param size
|
|
|
+ * 页面大小
|
|
|
+ * @return 获取到的数据
|
|
|
+ * @throws IllegalArgumentException
|
|
|
+ * @throws IllegalStateException
|
|
|
+ */
|
|
|
+ public PageResult<T> findPage(@NotEmpty("page") Integer page, @NotEmpty("size") Integer size)
|
|
|
+ throws IllegalArgumentException, IllegalStateException {
|
|
|
+ Query<T> query = createQuery();
|
|
|
+ return findPage(query, page, size);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据指定的条件分页查询数据
|
|
|
+ *
|
|
|
+ * @param filters
|
|
|
+ * 过滤条件,key-value的形式
|
|
|
+ * @param page
|
|
|
+ * 页码
|
|
|
+ * @param size
|
|
|
+ * 页面大小
|
|
|
+ * @return 查询到的数据
|
|
|
+ * @throws IllegalArgumentException
|
|
|
+ * @throws IllegalStateException
|
|
|
+ */
|
|
|
+ public PageResult<T> findPage(@NotEmpty("filters") Map<String, Object> filters, @NotEmpty("page") Integer page,
|
|
|
+ @NotEmpty("size") Integer size) throws IllegalArgumentException, IllegalStateException {
|
|
|
+ Query<T> query = createQuery();
|
|
|
+ filter(query, filters);
|
|
|
+ return findPage(query, page, size);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分页查询数据
|
|
|
+ *
|
|
|
+ * @param query
|
|
|
+ * the query used to match the documents to update
|
|
|
+ * @param page
|
|
|
+ * 页码
|
|
|
+ * @param size
|
|
|
+ * 页面大小
|
|
|
+ * @return 查询到的数据
|
|
|
+ * @throws IllegalArgumentException
|
|
|
+ * @throws IllegalStateException
|
|
|
+ */
|
|
|
+ public PageResult<T> findPage(@NotEmpty("query") Query<T> query, @NotEmpty("page") Integer page,
|
|
|
+ @NotEmpty("size") Integer size) throws IllegalArgumentException, IllegalStateException {
|
|
|
+ PageResult<T> result = new PageResult<>();
|
|
|
+ if (page < 1) {
|
|
|
+ throw new IllegalArgumentException("page 小于1");
|
|
|
+ }
|
|
|
+ if (size < 1) {
|
|
|
+ throw new IllegalArgumentException("size 小于1");
|
|
|
+ }
|
|
|
+ result.setPage(page);
|
|
|
+ result.setSize(size);
|
|
|
+
|
|
|
+ // 获取数据总数
|
|
|
+ long count = datastore.getCount(entityClass);
|
|
|
+ result.setTotalElement(count);
|
|
|
+ if (count == 0) {
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ int offset = (page - 1) * size;
|
|
|
+ if (offset >= count) {
|
|
|
+ throw new IllegalStateException("当前页码不存在");
|
|
|
+ }
|
|
|
+ if (page == 1) {
|
|
|
+ result.setFirst(true);
|
|
|
+ }
|
|
|
+ int totalPage = (int) Math.ceil(count / (1.0 * size));
|
|
|
+ result.setTotalPage(totalPage);
|
|
|
+ if (totalPage == page) {
|
|
|
+ result.setLast(true);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取指定页的数据
|
|
|
+ FindOptions findOptions = new FindOptions();
|
|
|
+ findOptions.skip(offset);
|
|
|
+ findOptions.limit(size);
|
|
|
+ MorphiaIterator<T, T> morphiaIterator = query.fetch(findOptions);
|
|
|
+ List<T> content = new ArrayList<>();
|
|
|
+ while (morphiaIterator.hasNext()) {
|
|
|
+ content.add(morphiaIterator.next());
|
|
|
+ }
|
|
|
+ result.setContent(content);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析json为指定对象
|
|
|
+ *
|
|
|
+ * @param json
|
|
|
+ * json数据
|
|
|
+ * @return 解析得到的对象
|
|
|
+ */
|
|
|
+ public T parse(@NotEmpty("json") String json) {
|
|
|
+ return JSONObject.parseObject(json, entityClass);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 为查询增加过滤条件
|
|
|
+ *
|
|
|
+ * @param query
|
|
|
+ * the query used to match the documents to update
|
|
|
+ * @param filters
|
|
|
+ * 过滤条件,key-value的形式
|
|
|
+ * <p>
|
|
|
+ * <b>Note</b>: Property is in the form of "name op" ("age >").
|
|
|
+ * <p/>
|
|
|
+ * <p>
|
|
|
+ * Valid operators are ["=", "==","!=", "<>", ">", "<", ">=",
|
|
|
+ * "<=", "in", "nin", "all", "size", "exists"]
|
|
|
+ * </p>
|
|
|
+ * <p/>
|
|
|
+ * <p>
|
|
|
+ * Examples:
|
|
|
+ * </p>
|
|
|
+ * <p/>
|
|
|
+ * <ul>
|
|
|
+ * <li>{@code filter("yearsOfOperation >", 5)}</li>
|
|
|
+ * <li>{@code filter("rooms.maxBeds >=", 2)}</li>
|
|
|
+ * <li>{@code filter("rooms.bathrooms exists", 1)}</li>
|
|
|
+ * <li>{@code filter("stars in", new Long[]{3, 4}) //3 and 4
|
|
|
+ * stars (midrange?)}</li>
|
|
|
+ * <li>{@code filter("quantity mod", new Long[]{4, 0}) //
|
|
|
+ * customers ordered in packs of 4)}</li>
|
|
|
+ * <li>{@code filter("age >=", age)}</li>
|
|
|
+ * <li>{@code filter("age =", age)}</li>
|
|
|
+ * <li>{@code filter("age", age)} (if no operator, = is assumed)
|
|
|
+ * </li>
|
|
|
+ * <li>{@code filter("age !=", age)}</li>
|
|
|
+ * <li>{@code filter("age in", ageList)}</li>
|
|
|
+ * <li>{@code filter("customers.loyaltyYears in", yearsList)}
|
|
|
+ * </li>
|
|
|
+ * </ul>
|
|
|
+ * <p/>
|
|
|
+ * <p>
|
|
|
+ * You can filter on id properties <strong>if</strong> this query
|
|
|
+ * is restricted to a Class<T>.
|
|
|
+ * @return the query used to match the documents to update
|
|
|
+ */
|
|
|
+ protected Query<T> filter(@NotEmpty("query") Query<T> query, @NotEmpty("filters") Map<String, Object> filters) {
|
|
|
+ Set<Entry<String, Object>> entrySet = filters.entrySet();
|
|
|
+ for (Entry<String, Object> entry : entrySet) {
|
|
|
+ query.filter(entry.getKey(), entry.getValue());
|
|
|
+ }
|
|
|
+ return query;
|
|
|
+ }
|
|
|
+}
|