当前位置: 首页 > backend >正文

MongoDB

文章目录

    • 创建或切换数据库
    • **1. 查询 (`find`)**
        • **查询全部数据**
        • **查询匹配字段**
        • **逻辑运算符**
        • 查所有集合
    • 2. 插入 (`insert`)
        • 插入单条数据
        • 插入多条数据
    • 3. 更新 (`update`)
        • 更新单条数据
        • 更新多条数据
    • 4. 删除 (`delete`)
        • 删除集合
        • 删除单条数据
        • 删除多条数据
    • 5. 排序 & 分页
        • 排序
        • 分页
    • 6. 地理位置查询
      • $geoWithin
      • $near
    • 其它
      • MongoDB Shell
      • linux安装MongoDB Shell
        • 登陆
      • SpringBoot集成MongoDb
        • 引入依赖
        • java和mongodb交互
          • 第一种,继承`MongoRepository`
          • 第二种,使用`MongoTemplate `
        • 示例
          • 删除
          • 工具类
      • planner returned error :: caused by :: unable to find index for $geoNear query' on server 192.168.26.128:27017. The full response is {"ok": 0.0, "errmsg": "error processing query: ns=location.vehicle_locationTree: $and\n vehicleId $eq \"1871467348318228480\"\n GEONEAR field=location maxdist=0.000156786 isNearSphere=1\nSort: {}\nProj: {}\n planner returned error :: caused by :: unable to find index for $geoNear query", "code": 291, "codeName": "NoQueryExecutionPlans"}

以下是 MySQL 和 MongoDB 有差异的地方的对比表格:

概念MySQLMongoDB
表(Table)集合(Collection)
字段/列字段/列(Column),结构固定字段(Field),结构灵活,可动态扩展
记录/行记录/行(Row),数据必须符合表结构文档(Document),以BSON格式存储,支持嵌套
主键主键(Primary Key),通常是自增的id_id字段,默认为ObjectId类型,非自增
查询语言SQL(Structured Query Language)MQL(MongoDB Query Language)
数据模型固定模式的关系型数据模型灵活模式的文档型数据模型
事务支持完全支持ACID属性支持单文档原子操作;4.0版本后支持多文档事务
关系处理使用外键实现表之间的关联嵌入式(Embedding)或引用(Referencing)表示关系
存储格式行存储格式BSON(类似于JSON)

这里是详细的 MongoDB 语法总结,每个部分都有清晰的 说明示例,帮助你快速掌握 MongoDB 查询、更新、插入、删除、索引、地理查询等操作。


创建或切换数据库

test> use location   // 切换或创建数据库
switched to db location

1. 查询 (find)

MongoDB 允许使用 find() 方法查询集合中的数据,并支持条件筛选、排序、分页等操作。

查询全部数据

查询 vehicle_location 集合中的所有数据:

db.vehicle_location.find({})
查询匹配字段
  • 单条件查询
    查询 vehicleId"1820377198820880384" 的车辆信息:
db.vehicle_location.find({ vehicleId: "1820377198820880384" })
  • 多条件查询
    查询tenantId=3, updateTime大于等于2024-07-01的,小于2025-07-02的数据
db.vehicle_location.find({ tenantId: "3",updateTime: {$gte: "2024-07-01",$lt: "2025-07-02"}
})
逻辑运算符

MongoDB 提供了一些常用的逻辑运算符:

操作符作用示例
$eq等于{ age: { $eq: 18 } }
$ne不等于{ age: { $ne: 18 } }
$gt大于{ age: { $gt: 18 } }
$lt小于{ age: { $lt: 18 } }
$gte大于等于{ age: { $gte: 18 } }
$lte小于等于{ age: { $lte: 18 } }
$in在数组内{ vehicleId: { $in: ["1820377198820880384", "1822090759331909632"] } }
$nin不在数组内{ vehicleId: { $nin: ["1820377198820880384"] } }

示例:查询 18 岁及以上的所有用户

db.users.find({ age: { $gte: 18 } })

查所有集合
show collections

在这里插入图片描述

2. 插入 (insert)

插入单条数据

vehicle_location 集合中插入一条新数据:

db.vehicle_location.insertOne({vehicleId: "1820377198820880384",vehicleNo: "甘A12456",location: [103.855549, 36.050249],updateTime: "2025-02-07T09:23:41"
})
插入多条数据
db.vehicle_location.insertMany([{vehicleId: "1820377198820880384",vehicleNo: "甘A12456",location: [103.855549, 36.050249],updateTime: "2025-02-07T09:23:41"},{vehicleId: "1822090759331909632",vehicleNo: "甘B56789",location: [103.857185, 36.054035],updateTime: "2025-02-07T09:24:41"}
])

3. 更新 (update)

更新单条数据

vehicleId"1820377198820880384"updateTime 改为 "2025-02-07T10:00:00"

db.vehicle_location.updateOne({ vehicleId: "1820377198820880384" },{ $set: { updateTime: "2025-02-07T10:00:00" } }
)
更新多条数据

updateTime 早于 "2025-02-07T09:30:00" 的车辆全部更新为 "2025-02-07T09:30:00"

db.vehicle_location.updateMany({ updateTime: { $lt: "2025-02-07T09:30:00" } },{ $set: { updateTime: "2025-02-07T09:30:00" } }
)

4. 删除 (delete)

删除集合
location> db.vehicleLocationBo.drop()
true
删除单条数据

删除 vehicleId"1820377198820880384" 的车辆:

db.vehicle_location.deleteOne({ vehicleId: "1820377198820880384" })
删除多条数据

删除 updateTime 早于 "2025-02-07T09:00:00" 的所有车辆:

db.vehicle_location.deleteMany({ updateTime: { $lt: "2025-02-07T09:00:00" } })

5. 排序 & 分页

排序

updateTime 降序 排列:

db.vehicle_location.find().sort({ updateTime: -1 })

updateTime 升序 排列:

db.vehicle_location.find().sort({ updateTime: 1 })
分页

跳过 10 条数据,获取 5 条数据:

db.vehicle_location.find().skip(10).limit(5)

6. 地理位置查询

$near 需要 2dsphere 索引,但$geoWithin不需要索引也能使用。

坐标格式:MongoDB GeoJSON 格式使用 [longitude, latitude](经度在前,纬度在后)。

距离单位:

maxDistance 单位为米(m)。

$geoNear 查询必须包含 spherical: true 来确保地球曲率计算。

$geoWithin

  • 查询经纬度500米内的数据
db.collection.find({location: {$geoWithin: {$centerSphere: [[经度, 纬度], // 替换为目标点的经纬度500 / 6378100 // 半径,单位是弧度(米转换为弧度)]}}
});
  • 查找某个区域内的点,例如查询某个矩形区域中的点
db.places.find({location: {$geoWithin: {$box: [[116.4035, 39.9140],  // 左下角坐标[116.4050, 39.9160]   // 右上角坐标]}}
});
  • 查询某个多边形区域内的点:
db.places.find({location: {$geoWithin: {$geometry: {type: "Polygon",coordinates: [[[116.4035, 39.9140],[116.4050, 39.9140],[116.4050, 39.9160],[116.4035, 39.9160],[116.4035, 39.9140] // 首尾坐标必须相同]]}}}
});
  • 判断点是否在区域内 ($geoIntersects)
db.areas.find({region: {$geoIntersects: {$geometry: { type: "Point", coordinates: [116.4040, 39.9150] }}}
});

$near

经纬度500米内的数据

db.collection.find({location: {$near: {$geometry: {type: "Point",coordinates: [经度, 纬度] // 替换为目标点的经纬度},$maxDistance: 500 // 单位是米}}
});

其它

MongoDB Shell

linux中用来连接mongo

linux安装MongoDB Shell

  • 1.1 添加 MongoDB 官方仓库
sudo tee /etc/yum.repos.d/mongodb-org.repo <<EOF
[mongodb-org-7.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/7/mongodb-org/7.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://pgp.mongodb.com/server-7.0.asc
EOF
  • 1.2 安装 ​​mongosh​​
sudo yum install -y mongodb-mongosh
  • 1…3 验证安装
mongosh --version

在这里插入图片描述

登陆
  • 默认直接输入mongosh,就会登录到本机端口为27017的mongo
mongosh
  • 如果端口改过,加上参数–port指定端口登陆
mongosh --port 38080

在这里插入图片描述

  • 如果远程的monggodb,则要加上ip和端口
mongosh --host <ip> --port <port>
  • 如果启用了身份验证,需要提供用户名、密码和认证数据库(通常是 ​​admin​​)
mongosh --host <hostname> --port <port> -u <username> -p <password> --authenticationDatabase <authDB>

例如

mongosh --host 192.168.1.100 --port 27017 -u myuser -p mypassword --authenticationDatabase admin
  • 如果已经登陆了,但是没有确认用户名密码,db.auth(用户名,密码)
kd> db.auth("zs","root")
{ ok: 1 }

SpringBoot集成MongoDb

引入依赖
        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency>
java和mongodb交互
第一种,继承MongoRepository
import org.springframework.data.mongodb.repository.MongoRepository;
import java.util.List;public interface UserRepository extends MongoRepository<User, String> {List<User> findByName(String name);
}
第二种,使用MongoTemplate
 @Autowiredprivate MongoTemplate mongoTemplate;public List<User> findUsersByNameAndAge(String name, int age) {Query query = new Query();Criteria criteria = Criteria.where("name").is(name).and("age").is(age);query.addCriteria(criteria);return mongoTemplate.find(query, User.class);}

查不到数据,需要指定集合名称
在find的第三个参数指定find(query, User.class,""),或者在接收的实体上面使用@Document(value = "")指定,不然查不到。

示例
package com.dh.taxi.data.utils;import com.dh.taxi.data.domain.bo.VehicleLocationBo;
import com.dh.taxi.data.domain.vo.VehicleLocationVo;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.domain.geo.Metrics;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;import javax.annotation.Resource;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;/*** 位置工具类*/
@Repository
public class LocationUtils {@Resourceprivate MongoTemplate mongoTemplate;/*** 查询车辆位置信息* @param bo* @return*/public List<VehicleLocationVo> getLocationList(VehicleLocationBo bo) {Query query = new Query();Criteria criteria = new Criteria();List<Criteria> criteriaList = new ArrayList<>();//String类型,等于该值的数据if (bo.getVehicleId() != null) {criteriaList.add(Criteria.where("vehicleId").is(bo.getVehicleId()));}if (bo.getVehicleNo() != null) {criteriaList.add(Criteria.where("vehicleNo").is(bo.getVehicleNo()));}// 时间类型,查询指定时间段,mongo中的数据的格式:ISODate('2025-05-09T02:20:39.566Z')if(bo.getIntervalTimeSeconds() != null ){//当前时间Instant now = Instant.now();//默认30s,30s内Instant tenSecondsAgo = now.minus(bo.getIntervalTimeSeconds(), java.time.temporal.ChronoUnit.SECONDS);//当前时间30秒内的数据criteriaList.add(Criteria.where("updateTime").gte(tenSecondsAgo).lte(now));}//  地理位置坐标,坐标Coordinate经纬度,半径RadiusMeter米的数据if (!CollectionUtils.isEmpty(bo.getCoordinate())) {List<Double> coordinate = bo.getCoordinate();Point center = new Point(coordinate.get(0), coordinate.get(1));Distance distance = new Distance(bo.getRadiusMeter(), Metrics.METERS); // 默认1000 米criteriaList.add(Criteria.where("coordinate").nearSphere(center).maxDistance(distance.getNormalizedValue()));}// 如果有条件就拼接if (!criteriaList.isEmpty()) {criteria.andOperator(criteriaList.toArray(new Criteria[0]));query.addCriteria(criteria);}return mongoTemplate.find(query, VehicleLocationVo.class);}/*** 上传位置信息** @return*/public VehicleLocationBo uploadLocation(VehicleLocationBo bo) {bo.setUpdateTime(LocalDateTime.now());return mongoTemplate.insert(bo);}}
删除
  • 常用删除方法
方法名说明
remove(Query query, Class<T> entityClass)根据条件删除匹配的数据(可以删除多条)
remove(Query query, String collectionName)指定集合删除(不绑定实体类)
findAndRemove(Query query, Class<T> entityClass)查找并删除一条数据(返回删除的实体)

  • 假设你要删除 name = "张三" 的数据:
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;@Service
public class UserService {private final MongoTemplate mongoTemplate;public UserService(MongoTemplate mongoTemplate) {this.mongoTemplate = mongoTemplate;}public void deleteUserByName(String name) {Query query = new Query(Criteria.where("name").is(name));mongoTemplate.remove(query, User.class);  // 默认使用 User 映射的集合}
}

  • 如果你只想删除一条数据(匹配的第一条):
User removedUser = mongoTemplate.findAndRemove(query, User.class);

  • 删除整个集合(清空表):
mongoTemplate.dropCollection(User.class);
// 或者指定集合名
mongoTemplate.dropCollection("user");

工具类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;import java.util.List;
import java.util.Optional;@Component
public class MongoTemplateUtil {@Autowiredprivate MongoTemplate mongoTemplate;/*** 插入单个数据到MongoDB集合* * @param entity 要插入的实体对象* @param <T> 实体类型* @return 插入后的实体对象*/public <T> T insert(T entity) {return mongoTemplate.insert(entity);}/*** 批量插入数据到MongoDB集合* * @param entities 要插入的实体对象列表* @param <T> 实体类型* @return 插入后的实体对象列表*/public <T> List<T> insertAll(List<T> entities) {return mongoTemplate.insertAll(entities);}/*** 更新MongoDB集合中的数据* * @param query 查询条件* @param entity 更新后的实体对象* @param entityClass 实体类类型* @param <T> 实体类型*/public <T> void update(Query query, T entity, Class<T> entityClass) {mongoTemplate.findAndModify(query, entity, entityClass);}/*** 根据条件查询单条数据* * @param query 查询条件* @param entityClass 实体类类型* @param <T> 实体类型* @return 查询到的单条数据(如果存在)*/public <T> Optional<T> findOne(Query query, Class<T> entityClass) {T result = mongoTemplate.findOne(query, entityClass);return Optional.ofNullable(result);}/*** 根据条件查询多条数据* * @param query 查询条件* @param entityClass 实体类类型* @param <T> 实体类型* @return 查询到的所有数据*/public <T> List<T> find(Query query, Class<T> entityClass) {return mongoTemplate.find(query, entityClass);}/*** 根据ID查询数据* * @param id 数据的ID* @param entityClass 实体类类型* @param <T> 实体类型* @return 查询到的数据(如果存在)*/public <T> Optional<T> findById(Object id, Class<T> entityClass) {T result = mongoTemplate.findById(id, entityClass);return Optional.ofNullable(result);}/*** 删除数据* * @param query 查询条件* @param entityClass 实体类类型* @param <T> 实体类型*/public <T> void delete(Query query, Class<T> entityClass) {mongoTemplate.remove(query, entityClass);}/*** 判断集合中是否存在符合条件的数据* * @param query 查询条件* @param entityClass 实体类类型* @param <T> 实体类型* @return 如果存在符合条件的数据,返回true;否则返回false*/public <T> boolean exists(Query query, Class<T> entityClass) {return mongoTemplate.exists(query, entityClass);}/*** 使用聚合查询MongoDB数据* * @param query 聚合查询条件* @param entityClass 实体类类型* @param <T> 实体类型* @return 聚合查询结果列表*/public <T> List<T> aggregate(Query query, Class<T> entityClass) {return mongoTemplate.aggregate(query, entityClass).getMappedResults();}/*** 根据条件查询并返回指定字段* * @param query 查询条件* @param entityClass 实体类类型* @param fields 要返回的字段名(可变参数)* @param <T> 实体类型* @return 查询到的所有数据*/public <T> List<T> findWithFields(Query query, Class<T> entityClass, String... fields) {if (!CollectionUtils.isEmpty(List.of(fields))) {query.fields().include(fields);}return mongoTemplate.find(query, entityClass);}
}
  • 测试
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;import java.util.List;@SpringBootTest
public class MongoTemplateUtilTest {@Autowiredprivate MongoTemplateUtil mongoTemplateUtil;@Testpublic void testInsert() {User user = new User("john_doe", "John", "Doe", 30);User insertedUser = mongoTemplateUtil.insert(user);System.out.println("Inserted user: " + insertedUser);}@Testpublic void testInsertAll() {User user1 = new User("alice_smith", "Alice", "Smith", 25);User user2 = new User("bob_jones", "Bob", "Jones", 28);List<User> users = mongoTemplateUtil.insertAll(List.of(user1, user2));users.forEach(user -> System.out.println("Inserted user: " + user));}@Testpublic void testFind() {Query query = new Query(Criteria.where("lastName").is("Doe"));List<User> users = mongoTemplateUtil.find(query, User.class);users.forEach(user -> System.out.println("Found user: " + user));}@Testpublic void testDelete() {Query query = new Query(Criteria.where("firstName").is("John"));mongoTemplateUtil.delete(query, User.class);System.out.println("Deleted users with first name 'John'.");}@Testpublic void testExists() {Query query = new Query(Criteria.where("firstName").is("Alice"));boolean exists = mongoTemplateUtil.exists(query, User.class);System.out.println("Does user exist? " + exists);}@Testpublic void testFindWithFields() {Query query = new Query(Criteria.where("lastName").is("Doe"));List<User> users = mongoTemplateUtil.findWithFields(query, User.class, "firstName", "lastName");users.forEach(user -> System.out.println("Found user with specified fields: " + user));}
}
  • 实体
public class User {private String id;private String username;private String firstName;private String lastName;private int age;// Constructors, getters and setterspublic User(String username, String firstName, String lastName, int age) {this.username = username;this.firstName = firstName;this.lastName = lastName;this.age = age;}// Getters and Setters omitted for brevity
}

planner returned error :: caused by :: unable to find index for $geoNear query’ on server 192.168.26.128:27017. The full response is {“ok”: 0.0, “errmsg”: “error processing query: ns=location.vehicle_locationTree: $and\n vehicleId $eq “1871467348318228480”\n GEONEAR field=location maxdist=0.000156786 isNearSphere=1\nSort: {}\nProj: {}\n planner returned error :: caused by :: unable to find index for $geoNear query”, “code”: 291, “codeName”: “NoQueryExecutionPlans”}

重要内容:caused by :: unable to find index for $geoNear query,查询中使用了 $eq 和 $near(地理空间查询)组合,但是字段没有设置索引,设置索引就好了

db.集合名.createIndex({ "字段名": "2dsphere" })
http://www.xdnf.cn/news/5513.html

相关文章:

  • wget、curl 命令使用场景与命令实践
  • 数据并行基础概念知识
  • openai接口参数max_tokens改名max-completion-tokens?
  • 17前端项目----支付弹框
  • 10.二叉搜索树中第k小的元素(medium)
  • 用pymysql操作数据库
  • POST请求 、响应、requests库高级用法
  • 甜蜜聊天话术库
  • Go语言标识符
  • 嵌入式STM32学习——433M无线遥控灯
  • AI-Talk开发板之驱动1.28寸圆屏
  • 深入理解 Polly:.NET Core 中的健壮错误处理策略
  • HTTP/1.1 host虚拟主机详解
  • USB学习【6】USB传输错误的处理
  • Typescript 源码核心流程
  • 【C语言练习】035. 编写结构体的函数
  • MySQL视图深度解析:从基础语法到高级应用
  • Mask-aware Pixel-Shuffle Down-Sampling (MPD) 下采样
  • vector 常见用法及模拟
  • 算法题(144):跳石头
  • 游戏逆向开发全阶段电子资料分享 – 从入门到精通实战教程
  • 软件架构师知识点总结
  • nfs挂载
  • python实现用户登录
  • 系统架构设计(四):架构风格总结
  • 常见的 DCGM 设备级别指标及其含义
  • 2024睿抗编程赛国赛-题解
  • 作业...
  • 【C/C++】无符号调试:GDB解栈实战指南
  • nrf52832 ble_app_templete_s132及nrf5_sdk packs下载安装