简介:java系列技术分享(持续更新中…)
初衷:一起学习、一起进步、坚持不懈
如果文章内容有误与您的想法不一致,欢迎大家在评论区指正
希望这篇文章对你有所帮助,欢迎点赞 收藏 ⭐留言更多文章请点击
MongoDB官网
: https://www.mongodb.com
MongoDB
是一个基于分布式文件存储的数据库。由C++语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案。是一个开源,高性能,支持海量数据存储的文档型数据库
,是NoSQL数据库产品的一种不支持表关系,只能操作单表
)支持数据分片
不常用
#查看所有的数据库
> show dbs
#创建数据库
#说明:在MongoDB中,数据库是自动创建的,通过use切换到新数据库中,进行插入数据即可自动创建数据库
#通过use关键字切换数据库
> use test
> show dbs #并没有创建数据库
> db.user.insert({id:1,name:'zhangsan'}) #插入数据
> show dbs
#查看表
> show tables
> show collections
#删除集合(表)
> db.user.drop()
true #如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false。
#删除数据库
> use test #先切换到要删除的数据中
> db.dropDatabase() #删除数据库
#插入数据
> db.user.insert({id:1,username:'zhangsan',age:20})
>
> db.user.find() #查询数据
#查询全部
> db.user.find()
#更新数据
> db.user.update({id:1},{$set:{age:22}})
#注意:如果这样写,会删除掉其他的字段
> db.user.update({id:1},{age:25})
#更新不存在的字段,会新增字段
> db.user.update({id:2},{$set:{sex:1}}) #更新数据
#更新不存在的数据,默认不会新增数据
> db.user.update({id:3},{$set:{sex:1}})
#如果设置第一个参数为true,就是新增数据
> db.user.update({id:3},{$set:{sex:1}},true)
#删除数据
> db.user.remove({})
#插入4条测试数据
db.user.insert({id:1,username:'zhangsan',age:20})
db.user.insert({id:2,username:'lisi',age:21})
db.user.insert({id:3,username:'wangwu',age:22})
db.user.insert({id:4,username:'zhaoliu',age:22})
> db.user.remove({age:22},true)
#删除所有数据
> db.user.remove({})
#插入测试数据
db.user.insert({id:1,username:'zhangsan',age:20})
db.user.insert({id:2,username:'lisi',age:21})
db.user.insert({id:3,username:'wangwu',age:22})
db.user.insert({id:4,username:'zhaoliu',age:22})
db.user.find() #查询全部数据
db.user.find({},{id:1,username:1}) #只查询id与username字段
db.user.find().count() #查询数据条数
db.user.find({id:1}) #查询id为1的数据
db.user.find({age:{$lte:21}}) #查询小于等于21的数据
db.user.find({$or:[{id:1},{id:2}]}) #查询id=1 or id=2
#分页查询:Skip()跳过几条,limit()查询条数
db.user.find().limit(2).skip(1) #跳过1条数据,查询2条数据
db.user.find().sort({id:-1}) #按照id倒序排序,-1为倒序,1为正序
1:升序索引 2:降序索引
#查看索引
db.user.getIndex()
#创建索引
db.user.createIndex({'age':1})
注解 | 描述 |
---|---|
@Document |
把一个java类声明为mongodb的文档,可以通过collection参数指定这个类对应的文档,标注在实体类上,类似于hibernate的entity注解。 |
@Id | 文档的唯一标识,在mongodb中为ObjectId,它是唯一的,不可重复,自带索引,通过时间戳+机器标识+进程ID+自增计数器(确保同一秒内产生的Id不会冲突)构成。 |
@Transient | 映射忽略的字段,该字段不会保存到mongodb,只作为普通的javaBean属性。 |
@Field |
映射 mongodb中的字段名,可以不加,不加的话默认以参数名为列名。 |
@Indexed | 声明该字段需要索引,建索引可以大大的提高查询效率。 |
@CompoundIndex |
复合索引的声明,建复合索引可以有效地提高多字段的查询效率。 |
@GeoSpatialIndexed | 声明该字段为地理信息的索引。 |
@DBRef | 关联另一个document对象。类似于mysql的表关联,但并不一样,mongo不会做级联的操作。 |
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-mongodbartifactId>
dependency>
spring:
data:
mongodb:
uri: mongodb://127.0.0.1:27017/tanhua
MongoDB 推荐id 为:ObjectId 类型
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(value="person")
public class Person {
@Id
private ObjectId id;
@Field("username")
private String name;
private int age;
private String address;
}
@SpringBootTest
public class MongoPersonTest {
@Autowired
private MongoTemplate mongoTemplate;
@Test
public void testSave() {
Person person = new Person();
person.setName("李四");
person.setAge(18);
person.setAddress("杭州");
mongoTemplate.save(person);
}
}
/**
* 条件查询
*/
@Test
public void testFind() {
//查询年龄小于20的所有人
Query query = new Query(Criteria.where("age").lt(20)); //查询条件对象
//查询
List<Person> list = mongoTemplate.find(query, Person.class);
for (Person person : list) {
System.out.println(person);
}
}
/**
* 分页查询
*/
@Test
public void testPage() {
Criteria criteria = Criteria.where("age").lt(30);
//1 查询总数
Query queryCount = new Query(criteria);
long count = mongoTemplate.count(queryCount, Person.class);
System.out.println(count);
//2 查询第二页,每页查询2条
Query queryLimit = new Query(criteria)
.skip(2) //开启查询的条数 (page-1)*size
.limit(5)//设置每页查询条数
.with(Sort.by(Sort.Order.desc("age")));//排序
List<Person> list = mongoTemplate.find(queryLimit, Person.class);
for (Person person : list) {
System.out.println(person);
}
}
/**
* 更新:
* 根据id,更新年龄 地址
*/
@Test
public void testUpdate() {
//1 条件 id对应age为18的数据
Query query = Query.query(Criteria.where("id").is("64ca7274b8287f3990363504"));
//2 更新的数据
Update update = new Update();
update.set("age", 20);
update.set("address", "上海");
mongoTemplate.updateFirst(query, update, Person.class);
}
/**
* 删除
*/
@Test
public void testRemove() {
Query query = Query.query(Criteria.where("id").is("64ca7274b8287f3990363504"));
mongoTemplate.remove(query, Person.class);
}
使用MongoDB进行地理位置搜索,选择索引类型为:2dsphere
(支持地球表面上进行几何计算)
存储地址数据使用GeoJsonPoint
搜索原理:已以某个位置为圆点,然后以搜索的距离为半径画圆。
注意事项:
2dsphere
GeoJsonPoint
对像不支持序列化,如果项目使用Dubbo
进行远程调用(使用RPC通信,采用二进制,需要对对象进行序列化处理)那么GeoJsonPoint
对象无法传递,需要通过经纬度传递后在整合。@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "user_location")
@CompoundIndex(name = "location_index", def = "{'location': '2dsphere'}")
public class UserLocation implements Serializable {
private static final long serialVersionUID = 45088645678765429970L;
@Id
private ObjectId id;
@Indexed
private Long userId; //用户id
private GeoJsonPoint location; //x:经度 y:纬度
private String address; //位置描述
private Long created; //创建时间
private Long updated; //更新时间
}
无法获取圆心到目标的距离
@Override
public void testQueryNear(Long userId, Double metre) {
//1. 根据用户id,查询用户的位置信息
Query query = Query.query(Criteria.where("userId").is(userId));
UserLocation location = mongoTemplate.findOne(query, UserLocation.class);
if (location == null) {
return null;
}
//2. 已当前用户位置绘制原点
GeoJsonPoint point = location.getLocation();
// GeoJsonPoint point = new GeoJsonPoint(110.123, 47.982);
//3. 绘制半径
Distance distance = new Distance(metre / 1000, Metrics.KILOMETERS);
//4. 绘制圆形
Circle circle = new Circle(point, distance);
//5. 查询
Query locationQuery = Query.query(Criteria.where("location").withinSphere(circle));
List<UserLocation> list = mongoTemplate.find(locationQuery, UserLocation.class);
for (UserLocation userLocation : list) {
System.out.println(userLocation);
}
}
public void testQueryNear(Double metre) {
//构建圆点
GeoJsonPoint point = new GeoJsonPoint(10.123, 47.982);
//创建NearQuery对象
NearQuery nearQuery = NearQuery.near(point, Metrics.KILOMETERS).maxDistance(metre / 1000, Metrics.KILOMETERS);
//查询
GeoResults<UserLocation> results = mongoTemplate.geoNear(nearQuery, UserLocation.class);
for (GeoResult<UserLocation> result : results) {
System.out.println(result.getContent());
System.out.println(result.getDistance().getValue());
}
}