java - Spring Data MongoDB,按长值搜索

标签 java spring mongodb spring-data-mongodb

我有一个存储在 mongo 中的对象,如下所示(当我查看文档时,这是它在 RoboMongo 中显示的方式):

{
    "_id": ObjectId("5e579c8674f69d1c1451f3ae"),
    ...
    "timestamp": NumberLong(1582800002779),
    ...
    "_class": "regular"
}

我存储的对象定义如下:

public class MyObjectModel {
    @Id
    @Field(value = ID_FIELD_NAME)
    private String id;
    @Field(value = TIMESTAMP_FIELD_NAME)
    private Long timestamp;
...
}

我的目的是获取时间范围内的对象列表。 这就是我使用 spring data mongo db 创建查询的方式:

    public List<Criteria> generateAllCriteria() {
        List<Criteria> criteriaList = new ArrayList<>();
        Optional.ofNullable(searchCriteria.getFromTimestamp()).map(ts -> criteriaList.add(generateFromTimestampCriteria(ts)));
        Optional.ofNullable(searchCriteria.getToTimestamp()).map(ts -> criteriaList.add(generateToTimestampCriteria(ts)));
        return criteriaList;
    }

    private Criteria generateFromTimestampCriteria(Long fromTimestamp) {
        Criteria critFromTimestamp = Criteria.where(TIMESTAMP_FIELD_NAME).gte(fromTimestamp);
        log.debug("From Timestamp criteria {}", critFromTimestamp.getCriteriaObject().toJson());
        return critFromTimestamp;
    }

    private Criteria generateToTimestampCriteria(Long toTimestamp) {
        Criteria critToTimestamp = Criteria.where(TIMESTAMP_FIELD_NAME).lt(toTimestamp);
        log.debug("To Timestamp criteria {}", critToTimestamp.getCriteriaObject().toJson());
        return critToTimestamp;
    }
...
    List<Criteria> criteriaList = generateAllCriteria();

    Criteria finalCriteria = new Criteria();
    finalCriteria = finalCriteria.andOperator(criteriaList.toArray(new Criteria[criteriaList.size()]));
    log.debug("Final criteria {}", finalCriteria);
    Query query = new Query();
    query.addCriteria(finalCriteria);

    List<MyObjectModel> myObjects = mongoTemplate.find(query, MyObjectModel.class);

当我显示它们时,查询如下:

From Timestamp criteria { "timestamp" : { "$gte" : { "$numberLong" : "1582714365857" } } }
To Timestamp criteria { "timestamp" : { "$lt" : { "$numberLong" : "1582887165858" } } }

最终的查询条件似乎是这样的:

o.s.data.mongodb.core.MongoTemplate - find using query: { "$and" : [{ "timestamp" : { "$gte" : { "$numberLong" : "1582714365857" } } }, { "timestamp" : { "$lt" : { "$numberLong" : "1582887165858" } } }] } fields: Document{{}} for class: class mypackage.model.MyObjectModel in collection: myObjectModel

乍一看似乎没问题,但是当我手动针对 Mongo 运行它时,它不会返回任何记录,在我看来,这意味着它在某种程度上是不正确的。 这是我在 Mongo 上运行的具体内容:

db.getCollection('my-collection').find({ "$and" : [{ "timestamp" : { "$gte" : { "$numberLong" : "1582707873806" } } }, { "timestamp" : { "$lt" : { "$numberLong" : "1582887165858" } } }] })

而且它显然不会返回任何记录。但是当我修改查询并删除 $numberLong 时:

db.getCollection('my-collection').find({ "$and" : [{ "timestamp" : { "$gte" : 1582707873806 } }, { "timestamp" : { "$lt" : 1582887165858 } }] })

它就像一个魅力。

有人可以启发我并解释我做错了什么吗?应该如何以正确的方式进行呢? 如何使 spring data mongo 创建正确的查询?

不用说,字符串和整数工作得很好。大约只有LONG秒。

提前感谢您的帮助。

最佳答案

据我了解:

  • from/to 是查询中唯一的参数
  • 两者都可以为空

并假设您的模型是:

public class Regular {
  @Id
  private String id;

  @Field
  private Long timestamp;
}

那么可能的解决方案(恕我直言,更短)是:

// exists(true) is a "hack" to return the elements in case both from/to are null
public List<Regular> find(Long from, Long to) {

  var criteria = where("timestamp").exists(true);
  if(from != null) {
    criteria.gte(from);
  }
  if(to != null) {
    criteria.lte(to);
  }

  return mongoTemplate.find(Query.query(criteria), Regular.class);
}
PS。我已经用 Spring Boot 2.2.4Mongo 3.6 检查过。

PS2。您仍然可以通过额外的 if 条件处理 from/to 都为 null 的情况,然后删除 exists(true)

关于java - Spring Data MongoDB,按长值搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60451930/

相关文章:

java - Tomcat 7 停止接收 HTTP 请求

java - HQL - 更新字段并在一个查询中返回结果值

java - 操作 JSP 输出的 Spring MVC 模型字段

java - 如何在 Java 中实现 addFields mongoDB 查询

mongodb - Mongodb启动失败— “aborting after fassert() failture”

c# - 使用 mongodb C# 驱动程序映射投影结果

java - 单击按钮时加载 XML 并以不同布局 ANDROID 显示

java - 如何在java中使用多个服务器以相同的顺序处理队列中的消息

java - 将扫描仪中的单词处理为字符串数组

java - Spring @async 子线程上下文 Multi-Tenancy