Monodb空间索引

1、用途介绍

因为项目需要,第一次接触mongodb的空间索引,之前没有了解过,就查询了一些资料,并将自己的学习经历记录下来,遗憾的是当初资料都没有记录下来资料出处,这里要向那些给我提供帮助的作者道个歉。我的项目是涉及到一个查询公司仓库附近的可用合作车辆,在大佬的推荐下,使用了空间索引,接下来说明具体思路。

2、建立思路

2.1、前提要求

首先保存数据的实体中需要有一个Double类型的一维数组,存放经纬度的信息。这时打开你的数据库管理工具,我用的Navicat,这时第一个重点来了:需要给已经生成的集合添加索引了,我之前创建的实体类是Location,一维数组的字段是loc;我们需要用到mongo的语法,
添加空间索引:db.Location.ensureIndex({"loc":"2d"})
成功后查询索引:db.Location.getIndexes()
就可以看到:
第一个索引是mongo建表自带的,第二个就是我们添加的空间索引
现在就完成一半了,并且空间索引是会一直存在的,不会出现你添加索引之前的数据能使用索引,之后添加的数据不能用的情况,所以添加一次即可。
如果添加错了,可用 db.Location.dropIndex(“loc_2d”) 命令来删除指定索引;

2.2、代码查询

我们公司用的是jdbc对数据库做操作,所以我对数据操作用的是MongoTemplate的模板类。代码如下

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 java.util.ArrayList;
import java.util.List;

 /**
     * 查询指定地点附近的可用车辆
     * @param lng   经度
     * @param lat   纬度
     * @param maxDistance   圆形范围半径,单位KM
     * @return	符合条件的结果集
     */
public List<Location> findNear(Double lng, Double lat, double maxDistance){
	Point point = new Point(lng, lat);		//lng是经度,lat是纬度
	Query query = new Query();
	//maxDistance必须是浮点型,整型的计算结果会为0
	Criteria criteria = Criteria.where("loc").near(point).maxDistance(maxDistance / 111);		
	List<Location> list = mongoTemplate.find(query, Location.class);
	if(list!=null && list.size()>0){
		return list;
	}else{
		return new ArrayList<Location>();
	}
}

这是通过圆心以指定半径来查找,还有另一种通过指定方形范围来查找,我也贴出来吧。代码如下

import org.springframework.data.geo.Box;
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;

/**
* 按方形查找
* @param lowerLeft  对角线的点的经纬度
* @param upperRight  对角线的点的经纬度
* @return
*/
public List<Location> findBoxWithin(Point lowerLeft, Point upperRight) {
    Query query = new Query(Criteria.where("loc").within(new Box(lowerLeft, upperRight)));
    return mongoTemplate.find(query, Location.class);
}

如有需要可以自己cv修改。

2.3、Navicat方式查询

这种我没怎么用,因为毕竟在生产环境中还是得用代码,不过还是贴出来以备不时之需。
自动查询前100条数据。

db.runCommand({
    "geoNear":"location",   //指定要在那个数据集里查询
    “near” : [0,0]          //指点目标点的经纬度
})

3、总结

在工作中还发现一个问题,实体类中给成员变量添加@Id注解或者成员变量名是id都会使主键固定,也就是mongo不会自动给每条数据生产_id了,在新增数据时,如果id属性值相同就会自动覆盖之前的旧数据。
空间索引还是有很大的用处的,就像地图搜索附近的应用,感觉也是用到了这个,但是不确定是不是mongodb,因为mysql好像也有空间索引,但是还没具体了解过。以后遇到了再补充。

操作monodb的c#封装,调用非常方便,可以继承,功能包括: 1、所有数据库操作 2、前台表格类数据获取 public List GetList(List lstColName, Document query, JqGridParam jqParam, ref int count),封装了通用的获取前台表格数据的方法,将在工程中减少大量数据库访问代码,有了这个后对前台表格类查询我们可以不用在Control里使用linq或者封装在Model里然后对前台定义视图类了,使用如下: try { JqGridParam jqParam = new JqGridParam(); jqParam.page = 1; jqParam.rows = 1000; MemberOper memOper = new MemberOper(); MongoBasicOper monOper = new MongoBasicOper(DTName.GROUP_MEMBER); int count = 0; //过滤条件 Document query = new Document(); if (!string.IsNullOrEmpty(find)) { MongoRegex reg = new MongoRegex(".*" + find + ".*"); query.Add(DColName.Name, reg); } query.Add(DColName.GroupId, g); Document[] docStatus = new Document[] { new Document(DColName.Status, RowStatus.Pass), new Document(DColName.Status, RowStatus.Admin) }; query.Add("$or", docStatus); //查询列 List lstColName = new List(); lstColName.Add(DColName.UserId); lstColName.Add(DColName.UserName); //查询数据 var lstRes = monOper.GetListEx(lstColName, query, jqParam, ref count); //转换返回值 JqGrid jg = new JqGrid(); if (count == 0) { return Json(jg.toNull(jqParam), JsonRequestBehavior.AllowGet); } var jsonData = jg.toJson(jqParam, count, lstRes, lstColName); jsonData.param = g; return Json(jsonData, JsonRequestBehavior.AllowGet); } catch (Exception e) { return Json(e.Message, JsonRequestBehavior.AllowGet); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值