mongo:基础 项目接入 与操作

mongodb学习

什么场景需要使用mongo?对比mysql的优势是什么?
两者最大的区别是mongo适合存储非结构化的数据,mysql适合存储结构化的数据。
除此之外,mongo的优点还包括:
1、分布式部署和水平扩展:MongoDB支持分布式部署和水平扩展,可以通过添加节点来扩展存储和查询能力,而MySQL的扩展方式是垂直扩展,需要升级硬件来提升性能。对于大数据量和高并发的应用场景,MongoDB更加适合。
2、查询性能:MongoDB的查询性能比MySQL更快,尤其是在非结构化数据的查询和聚合操作上。MongoDB支持复杂的查询和聚合操作,而MySQL的查询和聚合操作相对简单。

但是,在结构化数据的存储和查询、事务处理和ACID特性等方面,MySQL仍然是更好的选择。


1 mongodb基础语法与了解
https://www.runoob.com/mongodb/nosql.html
概念:
库 colletion数据集 document文件 field字段

ObjectId:唯一主键,可以很快的去生成和排序,包含 12 bytes,含义是:
前 4 个字节表示创建 unix 时间戳,格林尼治时间 UTC 时间,比北京时间晚了 8 个小时
接下来的 3 个字节是机器标识码
紧接的两个字节由进程 id 组成 PID
最后三个字节是随机数

由于 ObjectId 中保存了创建的时间戳,所以如果使用的是默认的id,则可以通过 getTimestamp 函数来获取文档的创建时间:
objectId.getTimestamp()


保存:
mongo中mongoTemplate或者MongoRepository实现的save,都是返回对应的整个documents,所以插入后id等信息的获取很方便。
注意如果save的对象中已经有id了,则mongo会将本次save操作视为update操作。
save():如果 _id 主键存在则更新数据,如果不存在就插入数据。该方法新版本中已废弃,可以使用 db.collection.insertOne() 或 db.collection.replaceOne() 来代替。
insert(): 若插入的数据主键已经存在,则会抛 org.springframework.dao.DuplicateKeyException 异常,提示主键重复,不保存当前数据。

标准的修改方式应该如下:
Query query = new Query(Criteria.where("name").is("John"));
Update update = new Update().set("age", 35);
mongoTemplate.updateFirst(query, update, Person.class);


springboot项目引入mongodb
1)引入springboot的mongo包
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
2)增加配置
spring: 
  data:
    mongodb:
      host: dds-8vb744d*
      port: 3717
      database: ai_test
      username: ai_test
      password: je***
      connection-pool:
        max-size: 50
        min-size: 20
3)连接池与连接建立
@Slf4j
@Configuration
@EnableMongoAuditing
public class MongoConfig extends AbstractMongoClientConfiguration {

    @NacosValue(value = "${spring.data.mongodb.host}", autoRefreshed = true)
    private String host;
    ......

    @Override
    protected String getDatabaseName() {
        return database;
    }

    @Override
    public MongoClient mongoClient() {
        log.info("[创建mongodb数据库连接]");
        MongoCredential credential = MongoCredential.createCredential(username, database, password.toCharArray());
        MongoClientSettings settings = MongoClientSettings.builder()
                .applyToClusterSettings(builder ->
                        builder.hosts(Arrays.asList(new ServerAddress(host, port), new ServerAddress(host2, port))))
                .applyToConnectionPoolSettings(builder ->
                        builder.maxSize(maxSize).minSize(minSize))
                .credential(credential)
                .build();
        return MongoClients.create(settings);
    }
}
4)mongo操作实例
@Api(tags = "c++题库 题单")
@Slf4j
@RestController
@RequestMapping(value = "/queList")
public class MongoExpController {

    @Autowired
    MongoTemplate mongoTemplate;

    private static final String COLLECTION_NAME = "users";


    @ApiOperation(value = "mongo操作数据库实例", notes = "mongo操作数据库实例")
    @GetMapping("/cleanJudgeData")
    public String clean(
            @ApiParam(value = "密钥", required = true) @RequestParam(required = true) String key
    ) {

        // 设置用户信息
        User user = new User();
        user.setId("13");
        user.setName("酒仙");
        // 存储用户信息,如果文档信息已经存在就执行更新
        User newUser = mongoTemplate.save(user);
        // 输出存储结果
        log.info("存储的用户信息为:{}", newUser);

        Query query = new Query();
        query.addCriteria(Criteria.where("name").is("酒仙"));
        String name = mongoTemplate.findOne(query, User.class).getName();
        return "abc";
    }
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "user")
public class User {

    @Id
    private String id;
    @Field("username")
    private String username;
    private String password;
    private String registerTime;
    private String phone;
    private String name;
    private String sex;
    private String age;
}


3 最佳实践
时间自维护
MongoConfig上开启自维护注释,@EnableMongoAuditing
    @CreatedDate
    @Field("create_time")
    private Date createTime;

    /**
     * 会话的修改时间
     */
    @LastModifiedDate
    @Field("update_time")
    private Date updateTime;
但是:如果id不是由mongo自动维护,那createTime上面的注释不会生效。
所以如果主键是研发来维护,那对应的createTime也是由研发维护。
说明:robot 3T查看数据时可以指定时间的时区,options->display dates in

id自增的实现
mongo一般的主键id是字符串格式的,但是可能因为一些特殊的要求(如分页),需要集合的主键是int类型的,此时实现方案如下:
新建一个计数器集合,包括名称和序号
@Document(collection = "counters")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Counters {
 
    @Id
    private String id;// 这里id就是集合名
 
    private Integer seq;// 这里seq就是集合名对应的主键当前值
 }

// 这里的类,用来维护主键id和序号
@Repository
public class CountersRespositoryImpl {

    @Autowired
    private MongoOperations mongoOperations;

    public Integer getNextSequence(String collectionName) {
        Query query = new Query(Criteria.where("_id").is(collectionName));
        Update update = new Update().inc("seq", 1);
        Counters counters = mongoOperations.findAndModify(query, update, Counters.class);
        if(counters == null){
            counters = Counters.builder().id(collectionName).seq(1).build();
            mongoOperations.save(counters);
        }
        return counters.getSeq();
    }
}

使用如下:
AiChatRecord chat = AiChatRecord.builder()
                .id(countersRespositoryImpl.getNextSequence("aiChatRecord"))
                .status(AiRequestStatusEnum.REQUEST_START.getValue())
                .createTime(new Date(System.currentTimeMillis()))
                .build();

https://zhuanlan.zhihu.com/p/497736109?utm_medium=social&utm_oi=639733965527846912
mongodb规范参考:https://segmentfault.com/a/1190000022926656
引擎:MongoDB 默认存储引擎为 MMAPv1,建议根据实际情况选择存储引擎。
集合:page size 压缩算法  leaf_page_max等参数设置

文档:_id建议自增
说明:MongoDB的表与InnoDB相似,都是索引组织表,数据内容跟在主键后,而_id是MongoDB中的默认主键,一旦_id的值为非自增,当数据量达到一定程度之后,每一次写入都可能导致主键的二叉树大幅度调整,这将是一个代价极大的写入, 所以写入就会随着数据量的增大而下降,所以一定不要在_id中写入自定义的内容。

索引应该使用小且区分度高的字段


mongodto中常用注解:
mongodb.core.mapping中的主要注解:
@Document:用于将Java类映射到MongoDB中的集合。
@Id:用于指定Java类中的属性作为MongoDB文档的_id字段。
@Field:用于将Java类中的属性映射到MongoDB文档中的字段。
@Indexed:用于创建MongoDB索引。
@CompoundIndex:用于创建MongoDB复合索引。
@GeoSpatialIndexed:用于创建MongoDB地理空间索引。
@TextIndexed:用于创建MongoDB全文索引。


关于@Index
如果在Java中的MongoDB domain类上添加了@Index注解,但是对应的集合已经存在一段时间,那么这个索引会在下一次应用程序启动时被创建。

在Spring Data MongoDB中,当应用程序启动时,会扫描所有带有@Document注解的类,并将它们映射到MongoDB中的集合。如果这些类上还带有@Index注解,则Spring Data MongoDB会为它们创建相应的索引。如果对应的集合中已经存在数据,则创建索引可能需要一些时间,具体时间取决于数据量和服务器性能。

因此,在实际开发中,最好在创建集合之前就定义好所需的索引。这样可以确保索引在应用程序启动时就被创建,从而避免在运行时对索引进行创建和维护所带来的性能开销。

https://zhuanlan.zhihu.com/p/497736109?utm_medium=social&utm_oi=639733965527846912

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值