mongodb基于地理位置查询实现围栏

本文涉及的产品
云数据库 MongoDB,通用型 2核4GB
简介: mongodb基于地理位置查询实现围栏

1、GeoJSON对象概述

以下内容是来自mongodb官方文档

指定GeoJSON数据,请使用具有以下内容的嵌入式文档:

  • type - 类型
  • coordinates - 指定对象坐标集

如果指定经度和纬度,第一个必须是经度,第二个为纬度

  • 有效的经度值位于-180到180之间
  • 有效的纬度值位于-90到90之间

数据格式:

: { type: , coordinates: }

eg.

"location":{
  "type":"Point",
  "coordinates":[106.522742,29.556538]
}

以下示例指定了GeoJSON LineString

{ type: "LineString", coordinates: [ [ 40, 5 ], [ 41, 6 ] ] }

多边形由GeoJSON LinearRing坐标数组组成。这些 LinearRings都是封闭的LineStrings。闭合LineStrings的至少具有四个坐标对,第一个和最后一个坐标必须一样,这样才能保证构建的图形是封闭的。连接曲面上两个点的线可能包含也可能不包含连接平面上这两个点的同一组坐标。连接曲面上两个点的线将是测地线。仔细检查坐标点,以免出现共享边,重叠和其他类型的相交的错误。

单环多边形

下面的例子指定了一个GeoJSON多边形,有一个外环,没有内环(或孔)。第一个和最后一个坐标必须匹配,以便关闭多边形。

{
  type: "Polygon",
  coordinates: [ [ [ 0 , 0 ] , [ 3 , 6 ] , [ 6 , 1 ] , [ 0 , 0  ] ] ]
}

对于只有一个环的多边形,该环不能自相交。

多环多边形

  • 第一个描述的环必须是外环
  • 外环不能自我相交
  • 任何内环必须完全被外环所包含
  • 内部环不能相互交叉或重叠。内部环不能共享一条边
{
  type : "Polygon",
  coordinates : [
     [ [ 0 , 0 ] , [ 3 , 6 ] , [ 6 , 1 ] , [ 0 , 0 ] ],
     [ [ 2 , 2 ] , [ 3 , 3 ] , [ 4 , 2 ] , [ 2 , 2 ] ]
  ]
}

Diagram of a Polygon with internal ring. 图片来自mongodb官网

GeoJSON MultiPoint 嵌入的文件编码为一个点的列表

{
  type: "MultiPoint",
  coordinates: [
     [ -73.9580, 40.8003 ],
     [ -73.9498, 40.7968 ],
     [ -73.9737, 40.7648 ],
     [ -73.9814, 40.7681 ]
  ]
}

以下示例指定一个 GeoJSON MultiLineString

{
  type: "MultiLineString",
  coordinates: [
     [ [ -73.96943, 40.78519 ], [ -73.96082, 40.78095 ] ],
     [ [ -73.96415, 40.79229 ], [ -73.95544, 40.78854 ] ],
     [ [ -73.97162, 40.78205 ], [ -73.96374, 40.77715 ] ],
     [ [ -73.97880, 40.77247 ], [ -73.97036, 40.76811 ] ]
  ]
}

以下示例指定一个GeoJSON MultiPolygon

{
  type: "MultiPolygon",
  coordinates: [
     [ [ [ -73.958, 40.8003 ], [ -73.9498, 40.7968 ], [ -73.9737, 40.7648 ], [ -73.9814, 40.7681 ], [ -73.958, 40.8003 ] ] ],
     [ [ [ -73.958, 40.8003 ], [ -73.9498, 40.7968 ], [ -73.9737, 40.7648 ], [ -73.958, 40.8003 ] ] ]
  ]
}

以下示例存储 GeometryCollection 类型的坐标,即几何集的坐标

{
  type: "GeometryCollection",
  geometries: [
     {
       type: "MultiPoint",
       coordinates: [
          [ -73.9580, 40.8003 ],
          [ -73.9498, 40.7968 ],
          [ -73.9737, 40.7648 ],
          [ -73.9814, 40.7681 ]
       ]
     },
     {
       type: "MultiLineString",
       coordinates: [
          [ [ -73.96943, 40.78519 ], [ -73.96082, 40.78095 ] ],
          [ [ -73.96415, 40.79229 ], [ -73.95544, 40.78854 ] ],
          [ [ -73.97162, 40.78205 ], [ -73.96374, 40.77715 ] ],
          [ [ -73.97880, 40.77247 ], [ -73.97036, 40.76811 ] ]
       ]
     }
  ]
}

2、基于springboot的围栏应用

2.1 搭建环境

使用idea的spring initializ创建新的项目spring-boot-mongo-geo项目,选择以下依赖:

 <!-- web -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- mongodb -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

项目包结构如下:

image.png

2.2 围栏实现

此处我们实现两种类型的围栏

  • 圆形(Point)
  • 多边形(Polygon)

创建圆形存储实体对象

package com.mongo.geo.model;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexed;
import org.springframework.data.mongodb.core.mapping.Document;

/**
 * <pre>
 * Title: 圆形围栏
 *
 * Description:
 * <pre>
 * @author Steve.Chang
 **/
@Document(value = "m_circle_fence")
public class CircleFence {

    @Id
    private String id;

    /**
     * 用户编号
     */
    private String userNo;

    /**
     * 半径距离
     */
    private Long distance;

    /**
     * 地理位置
     * @GeoSpatialIndexed - 创建2dsphere索引
     */
    @GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)
    private GeoJsonPoint location;


    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getMerchantNo() {
        return merchantNo;
    }

    public void setMerchantNo(String merchantNo) {
        this.merchantNo = merchantNo;
    }

    public GeoJsonPoint getLocation() {
        return location;
    }

    public void setLocation(GeoJsonPoint location) {
        this.location = location;
    }

    public Long getDistance() {
        return distance;
    }

    public void setDistance(Long distance) {
        this.distance = distance;
    }
}

多边形存储实体对象

package com.mongo.geo.model;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexed;
import org.springframework.data.mongodb.core.mapping.Document;

/**
 * <pre>
 * Title: 多边形围栏
 *
 * Description:
 * <pre>
 * @author Steve.Chang
 **/
@Document(value = "m_polygon_fence")
public class PolygonFence {

    @Id
    private String id;

    /**
     * 用户编号
     */
    private String userNo;

    /**
     * 地理位置
     * @GeoSpatialIndexed - 创建2dsphere索引
     */
    @GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)
    private GeoJsonPolygon location;


    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getMerchantNo() {
        return merchantNo;
    }

    public void setMerchantNo(String merchantNo) {
        this.merchantNo = merchantNo;
    }

    public GeoJsonPolygon getLocation() {
        return location;
    }

    public void setLocation(GeoJsonPolygon location) {
        this.location = location;
    }
}

Respository

实现有两种方式

  • MongoTemplate (适用于复杂的查询,自己可以灵活控制)
  • 继承 MongoRepository (提供一些基础的模板方法,当然也可以自定义一些派生方法)

此处使用MongoTemplate方式实现

Service

package com.mongo.geo.service;

import com.mongo.geo.model.CircleFence;
import com.mongo.geo.model.PolygonFence;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Metrics;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;

/**
 * <pre>
 * Title: 围栏service
 *
 * Description:
 * <pre>
 * @author Steve.Chang
 **/
@Service
public class FenceService {

    private final MongoTemplate mongoTemplate;

    public FenceService(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }

    /**
     * 创建原型围栏
     *
     * @param fence CircleFence
     */
    public void createCircle(CircleFence fence) {
        mongoTemplate.save(fence);
    }

    /**
     * 创建多边形围栏
     *
     * @param fence CircleFence
     */
    public void createPolygon(PolygonFence fence) {
        mongoTemplate.save(fence);
    }

    /**
     * 坐标是否在圆形围栏中
     *
     * @param userNo   userNo
     * @param point    geo json point
     * @param distance circle radius(unit: Miles)
     * @return
     */
    public boolean existsCircle(String userNo, GeoJsonPoint point, Long distance) {
        // 指定圆的半径
        Distance dis = new Distance(distance, Metrics.KILOMETERS);
        // 构造圆
        Circle circle = new Circle(point, dis);
        // 构造查询对象
        Criteria criteria = Criteria.where("userNo").is(userNo)
                .and("localtion").withinSphere(circle);
        Query query = Query.query(criteria);
        List<CircleFence> fences = mongoTemplate.find(query, CircleFence.class);
        return !CollectionUtils.isEmpty(fences);
    }

    /**
     * 坐标是否在多边形形围栏中
     *
     * @param userNo userNo
     * @param point  geo json point
     * @return
     */
    public boolean existsPolygon(String userNo, GeoJsonPoint point) {
        // 构造查询对象
        Criteria criteria = Criteria.where("userNo").is(userNo)
                .and("localtion").intersects(point);
        Query query = Query.query(criteria);

        List<CircleFence> fences = mongoTemplate.find(query, CircleFence.class);
        return !CollectionUtils.isEmpty(fences);
    }
}

以上查询用到了以下几个geo查询方法:

  • $geoIntersects

选择地理空间数据与指定的GeoJSON对象相交的文档 ;也就是说,数据和指定对象的交集是非空的。 $geoIntersects操作符使用$geometry操作符来指定GeoJSON对象。要使用默认的坐标参考系统(CRS)指定GeoJSON多边形或MutiPolygon(多个多边形类型),请使用以下语法。

eg.

{
  <location field>: {
     $geoIntersects: {
        $geometry: {
           type: "Polygon" ,
           coordinates: [ <coordinates> ],
           crs: {
              type: "name",
              properties: { name: "urn:x-mongodb:crs:strictwinding:EPSG:4326" }
           }
        }
     }
  }
}
  • $geoWithin

选择具有完全存在于指定形状内的地理空间数据的文档。指定的形状可以是GeoJSON多边形(单环或多环),也可以是GeoJSON多重多边形,或由传统坐标对定义的形状。$geoWithin操作符使用$geometry操作符来指定GeoJSON对象。要使用默认的坐标参考系统(CRS)指定GeoJSON多边形或多多边形,请使用以下语法。

{
   <location field>: {
      $geoWithin: {
         $geometry: {
           type: "Polygon" ,
           coordinates: [ <coordinates> ],
           crs: {
              type: "name",
              properties: { name: "urn:x-mongodb:crs:strictwinding:EPSG:4326" }
           }
         }
      }
   }
}
  • $near

指定一个点,地理空间查询会从最近到最远的地方返回文件。

$near操作符可以指定一个GeoJSON点或传统的坐标点。

$near需要一个地理空间索引。

​ - 如果指定的是GeoJSON点,需要2dsphere索引。

​ - 如果指定一个使用传统坐标的点,则需要2d索引。

要指定一个GeoJSON点,$near操作符需要一个2dsphere索引,其语法如下。

{
   <location field>: {
     $near: {
       $geometry: {
          type: "Point" ,
          coordinates: [ <longitude> , <latitude> ]
       },
       $maxDistance: <distance in meters>,
       $minDistance: <distance in meters>
     }
   }
}
  • $nearSphere

​ 指定一个点,地理空间查询会从最近到最远的地方返回文件。MongoDB使用球面几何学计算$nearSphere的距离。

$nearSphere需要一个地理空间的索引。

​ - 2dsphere索引用于定义为GeoJSON点的位置数据

   - 2d索引,用于定义为传统坐标对的位置数据。要在GeoJSON点上使用2d索引,请在GeoJSON对象的坐标域上创建索引。$nearSphere操作符可以指定一个GeoJSON点或传统坐标点。

eg.

{
  $nearSphere: {
     $geometry: {
        type : "Point",
        coordinates : [ <longitude>, <latitude> ]
     },
     $minDistance: <distance in meters>,
     $maxDistance: <distance in meters>
  }
}

要使用传统坐标指定点,请使用以下语法:

{
  $nearSphere: [ <x>, <y> ],
  $minDistance: <distance in radians>,
  $maxDistance: <distance in radians>
}

如果您将经度和纬度用于旧版坐标,请先指定经度,然后再指定纬度。

  • $box

​ 为地理空间 $geoWithin 查询指定一个矩形,以根据其基于点的位置数据返回该矩形范围内的文档。与$box运算符一起使用时,$geoWithin将基于网格坐标返回文档,并且不会查询GeoJSON形状。

​ 要使用$box运算符,必须在数组对象中指定矩形的左下角和右上角,语法如下:

{
  <location field>: {
     $geoWithin: {
        $box: [
          [ <bottom left coordinates> ],
          [ <upper right coordinates> ]
        ]
     }
  }
}
  • $center

​ $center操作符为$geoWithin查询指定了一个圆。该查询返回在圆圈范围内的遗留坐标对。该操作符不返回GeoJSON对象。

​ 要使用$center操作符,请指定一个包含以下内容的数组。

​ - 圆的中心点的网格坐标。

​ - 圆的半径,以坐标系统所使用的单位来测量。

{
   <location field>: {
      $geoWithin: { $center: [ [ <x>, <y> ] , <radius> ] }
   }
}
  • $centerSphere

​ 为使用球面几何的地理空间查询定义一个圆。该查询会返回在圆圈范围内的文件。你可以在GeoJSON对象和传统的坐标对上使用$centerSphere操作符。

​ 使用$centerSphere,指定一个包含的数组:

​ - 圆的中心点的网格坐标

​ - 以弧度为单位的圆的半径。要计算弧度,请参阅《Calculate Distance Using Spherical Geometry》)

{
   <location field>: {
      $geoWithin: { $centerSphere: [ [ <x>, <y> ], <radius> ] }
   }
}
  • $geometry

​ $geometry操作符指定了一个GeoJSON几何体,用于以下地理空间查询操作符。$geoWithin, $geoIntersects, $near, 和$nearSphere。$geometry使用EPSG:4326作为默认的坐标参考系统(CRS)。

要指定使用默认CRS的GeoJSON对象,请使用以下$geometry的示例。

$geometry: {
   type: "<GeoJSON object type>",
   coordinates: [ <coordinates> ]
}

要指定一个带有自定义MongoDB CRS的单环GeoJSON多边形,请使用以下示例(仅对$geoWithin和$geoIntersects可用)。

$geometry: {
   type: "Polygon",
   coordinates: [ <coordinates> ],
   crs: {
      type: "name",
      properties: { name: "urn:x-mongodb:crs:strictwinding:EPSG:4326" }
   }
}
  • $maxDistance

​ $maxDistance操作符将地理空间$near或$nearSphere查询的结果限制在指定距离内。最大距离的测量单位由使用的坐标系统决定。对于GeoJSON点对象,指定的距离是米,而不是弧度。你必须为$maxDistance指定一个非负数。

2dsphere和2d地理空间索引都支持$maxDistance:

db.places.find( {
   loc: { $near: [ -74 , 40 ],  $maxDistance: 10 }
} )
  • $minDistance

​ 将地理空间的$near或$nearSphere查询的结果过滤到与中心点至少有指定距离的文件。

​ 如果$near或$nearSphere查询指定中心点为GeoJSON点,则指定距离为非负数,单位为米。

​ 如果$nearSphere查询将中心点指定为遗留坐标对,则将距离指定为弧度的非负数。如果查询指定中心点为GeoJSON点,$near只能使用2dsphere索引。

重要

如果指定纬度和经度坐标,请先列出经度,然后再列出 纬度

  • 有效的经度值介于-180和之间180,包括两者之间。
  • 有效的纬度值介于-90和之间90,包括在内。

db.places.find(
   {
     location:
       { $near :
          {
            $geometry: { type: "Point",  coordinates: [ -73.9667, 40.78 ] },
            $minDistance: 1000,
            $maxDistance: 5000
          }
       }
   }
)
  • $polygon

指定一个多边形,用于对遗留坐标对进行地理空间$geoWithin查询。该查询返回在多边形范围内的坐标对。该运算符不对GeoJSON对象进行查询。

要定义多边形,请指定一个坐标点阵列:

{
   <location field>: {
      $geoWithin: {
         $polygon: [ [ <x1> , <y1> ], [ <x2> , <y2> ], [ <x3> , <y3> ], ... ]
      }
   }
}

注意: 最后一个点必须要和第一个点相连,也就是第一个点和最后一个点要保持一样。

​ $polygon运算符使用平坦的(平面)几何图形来计算距离。应用程序可以使用$polygon而无需地理空间索引。然而,地理空间索引支持比无索引快的查询。

只有2D地理空间索引支持$polygon操作。

  • $uniqueDocs

​ 自2.6版起不再使用:地理空间查询不再返回重复的结果。$uniqueDocs操作符对结果没有影响。
对一个地理空间查询只返回一次文件,即使该文件与查询多次匹配。

Controller

package com.mongo.geo.controller;

import com.mongo.geo.controller.vo.CircleFenceParamVO;
import com.mongo.geo.controller.vo.FenceCheckParamVO;
import com.mongo.geo.controller.vo.FencePoint;
import com.mongo.geo.controller.vo.PolygonFenceParamVO;
import com.mongo.geo.model.CircleFence;
import com.mongo.geo.model.PolygonFence;
import com.mongo.geo.service.FenceService;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

/**
 * <pre>
 * Title: 围栏
 *
 * Description:
 * <pre>
 * @author Steve.Chang
 **/
@RestController
@RequestMapping("api/fence")
public class FenceController {

    private final FenceService fenceService;

    public FenceController(FenceService fenceService) {
        this.fenceService = fenceService;
    }

    /**
     * 创建圆形围栏
     *
     * @param paramVO CircleFenceParamVO
     * @return
     */
    @PostMapping("circle")
    public ResponseEntity createCircle(@RequestBody CircleFenceParamVO paramVO) {
        CircleFence circle = new CircleFence();
        circle.setMerchantNo(paramVO.getMerchantNo());
        circle.setLocation(new GeoJsonPoint(paramVO.getLongitude(), paramVO.getLatitude()));
        fenceService.createCircle(circle);
        return ResponseEntity.ok().body("");
    }

    /**
     * 创建多边形围栏
     *
     * @param paramVO CircleFenceParamVO
     * @return
     */
    @PostMapping("polygon")
    public ResponseEntity createPolygon(@RequestBody PolygonFenceParamVO paramVO) {
        PolygonFence polygonFence = new PolygonFence();
        polygonFence.setMerchantNo(paramVO.getMerchantNo());

        List<Point> points = new ArrayList<>();
        for (FencePoint coordinate : paramVO.getCoordinates()) {
            points.add(new Point(coordinate.getLongitude(), coordinate.getLatitude()));
        }

        GeoJsonPolygon polygon = new GeoJsonPolygon(points);
        polygonFence.setLocation(polygon);
        fenceService.createPolygon(polygonFence);
        return ResponseEntity.ok().body("");
    }

    /**
     * 原型围栏检查
     *
     * @param paramVO FenceCheckParamVO
     * @return ResponseEntity
     */
    @GetMapping("circle/warning")
    public ResponseEntity existsCircle(@RequestBody FenceCheckParamVO paramVO) {
        boolean result = fenceService.existsCircle(paramVO.getMerchantNo(), new GeoJsonPoint(paramVO.getLongitude(),
                paramVO.getLatitude()), paramVO.getDistance());
        return ResponseEntity.ok().body(result ? "围栏内" : "围栏外");
    }

    /**
     * 多边形围栏检查
     *
     * @param paramVO FenceCheckParamVO
     * @return ResponseEntity
     */
    @GetMapping("polygon/warning")
    public ResponseEntity existsPolygon(@RequestBody FenceCheckParamVO paramVO) {
        boolean result = fenceService.existsPolygon(paramVO.getMerchantNo(), new GeoJsonPoint(paramVO.getLongitude(),
                paramVO.getLatitude()));
        return ResponseEntity.ok().body(result ? "围栏内" : "围栏外");
    }

}

最后使用postman工具调试结果,此处就不具体贴图了。

特别说明

mongodb中默认是使用WGS84做计算的,使用的时候请注意要转换成对应格式的数据。

文章如有不妥支出,请指正。

相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。 &nbsp; 相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
目录
相关文章
|
8月前
|
JSON NoSQL MongoDB
mongodb基本操作,增删改查,查询,索引,权限机制
mongodb基本操作,增删改查,查询,索引,权限机制
|
8月前
|
SQL NoSQL 关系型数据库
MongoDB复杂分组聚合查询1
MongoDB复杂分组聚合查询1
417 0
|
7月前
|
NoSQL MongoDB 索引
开心档-软件开发入门之MongoDB 覆盖索引查询
开心档-软件开发入门之MongoDB 覆盖索引查询
47 0
|
4月前
|
NoSQL 关系型数据库 MySQL
深入了解 Python MongoDB 查询:find 和 find_one 方法完全解析
在 MongoDB 中,我们使用 find() 和 find_one() 方法来在集合中查找数据,就像在MySQL数据库中使用 SELECT 语句来在表中查找数据一样
67 1
|
23天前
|
JSON NoSQL MongoDB
mongodb导出聚合查询的数据
mongodb导出聚合查询的数据
|
4月前
|
存储 NoSQL 安全
go 连接mongodb执行查询的代码
在Go语言中,你可以使用官方的MongoDB驱动程序 `"go.mongodb.org/mongo-driver/mongo"` 来连接MongoDB并执行查询。以下是一个简单的示例代码,演示如何连接MongoDB并执行查询: 首先,确保你已经安装了MongoDB驱动程序: ```bash go get go.mongodb.org/mongo-driver/mongo ``` 然后,可以使用以下示例代码: ```go package main import ( "context" "fmt" "log" "time" "go.mongodb.org/mongo-driv
|
10月前
|
SQL NoSQL 数据可视化
【国庆弯道超车系列】MongoDB进阶之查询(一)
【国庆弯道超车系列】MongoDB进阶之查询(一)
90 0
|
5月前
|
缓存 NoSQL MongoDB
MongoDB数据库查询性能提高40倍?
MongoDB数据库查询性能提高40倍?
99 0
|
5月前
|
NoSQL JavaScript 前端开发
MongoDB【CRUD练习-条件查询-文档关系】
MongoDB【CRUD练习-条件查询-文档关系】
|
6月前
|
JSON NoSQL MongoDB
MongoDB数据库查询性能提高40倍
MongoDB数据库查询性能提高40倍
MongoDB数据库查询性能提高40倍