techiall / Blog

🍋 [My Blog] See discussions
https://github.com/techiall/Blog/discussions
MIT License
8 stars 1 forks source link

MongoTemplate 使用总结 #55

Open techiall opened 5 years ago

techiall commented 5 years ago

本文的示例如下,集合名称为 Message。

{
  "_id" : ObjectId("5ccaff6ff86fa11cd44b68e1"),
  "title" : "title",
  "content" : "content",
  "editorId" : "1",
  "list" : [{
      "id" : "2",
      "isRead" : "READ",
      "readTime" : ISODate("2019-05-02T14:33:58.558Z")
    },
    {
      "id" : "3",
      "isRead" : "READ",
      "readTime" : ISODate("2019-05-02T14:35:51.658Z")
    }],
  "createTime" : ISODate("2019-05-02T14:32:15.284Z")
}

自动注入该变量。

@Autowired
private MongoTemplate mongoTemplate;

根据 ID 进行查找

可能你第一反应写出以下代码,但是结果不如你所愿,他返回的集合是空。

Query query = Query.query(Criteria.where("_id").in("5ccaff6ff86fa11cd44b68e1");
mongoTemplate.find(query, Message.class);

我们改成一下这种方式即可查询得到。引入 ObjectId 即可。

import org.bson.types.ObjectId; // 引入 ObjectId;

Query query = Query.query(Criteria.where("_id")
                          .in(new ObjectId("5ccaff6ff86fa11cd44b68e1"));
mongoTemplate.find(query, Message.class);

查询嵌入文档里的字段

我们可以用 . 点表示法来查询嵌入文档里的字段。格式为 <嵌入的文档名>.<字段>

假设我们需要根据 list 中 id 进行查询。使用 . 点表示法进行查询,方法如下

Query query = Query.query(Criteria.where("list.id").in("2"));
mongoTemplate.find(query, Message.class);

更新嵌入文档里面的字段

list 文档里面是一个数组,如果我们对 list 中的 id 字段为 "2" 进行更新,那我们得先查到这条数据,接着在对他进行更新。若只想更新一条,可以使用 mongoTemplate.updateFirst,更新多条,可以使用 mongoTemplate.findAndModify 或者 mongoTmplate.updateMulti

下面以 mongoTmplate.updateMulti 为例。

mongoTemplate.updateMulti(
    Query.query(Criteria.where("_id").in(new ObjectId("5ccaff6ff86fa11cd44b68e1"))),
    Update.update("list.$.isRead", "READ")
        .set("list.$.readTime", new Date()),
    Message.class
);

update 用到了 $ 运算符, $ 运算符充当占位符,表示访问嵌入文档中的字段。你可以把 $ 当成一个下标。查询的时候不需要用 $,更新的时候就需要。

unwind 拆分字段

个人觉得这方法超级好用!

我们想把 list 中的每一个元素输出成一份新的文档,也就是变成

{
  "_id" : ObjectId("5ccaff6ff86fa11cd44b68e1"),
  "title" : "title",
  "content" : "content",
  "editorId" : "1",
  "list" : {
      "id" : "2",
      "isRead" : "READ",
      "readTime" : ISODate("2019-05-02T14:33:58.558Z")
    },
  "createTime" : ISODate("2019-05-02T14:32:15.284Z")
},
{
  "_id" : ObjectId("5ccaff6ff86fa11cd44b68e1"),
  "title" : "title",
  "content" : "content",
  "editorId" : "1",
  "list" : {
      "id" : "3",
      "isRead" : "READ",
      "readTime" : ISODate("2019-05-02T14:35:51.658Z")
    },
  "createTime" : ISODate("2019-05-02T14:32:15.284Z")
}

我们就需要 unwind 这个操作符了。他是属于 mongodb 中的聚合查询。

我们需要在被操作的字段名称前加上 $ 符号,在这个示例之中需要被操作的字段也就是 list

mongoTemplate 操作如下。我们需要定义一个新的类来接受返回的数据,如果懒得定义,使用 java.lang.Object 来接收也是可以的。

Aggregation aggregation = Aggregation.newAggregation(
    Aggregation.unwind("$list"),
);
mongoTemplate
    .aggregate(aggregation, Message.class, NotifyMessage.class)
    // 以上那句也可以改成
    //  .aggregate(aggregation, Message.class, Object.class)
    .getMappedResults()
    .stream()
    .collect(Collectors.toList());

参考文档