初步学习 MongoDB

 

是什么?

MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似jsonbson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引

就是一个数据库,这个数据库,存储的是json字符串类型的数据。支持 crud操作。

MongoDB 的设计目标是高性能、可扩展、易部署、易使用,存储数据非常方便。其主要功能特性如下。

(1)面向集合存储,容易存储对象类型的数据。在MongoDB 中数据被分组存储在集合中,集合类似RDBMS 中的表,一个集合中可以存储无限多的文档。

(2)模式自由,采用无模式结构存储。在MongoDB 中集合中存储的数据是无模式的文档,采用无模式存储数据是集合区别于RDBMS 中的表的一个重要特征。

(3)支持完全索引,可以在任意属性上建立索引,包含内部对象。MongoDB的索引和RDBMS 的索引基本一样,可以在指定属性、内部对象上创建索引以提高查询的速度。除此之外,MongoDB 还提供创建基于地理空间的索引的能力。

(4)支持查询。MongoDB 支持丰富的查询操作,MongoDB 几乎支持SQL中的大部分查询。

(5)强大的聚合工具。MongoDB 除了提供丰富的查询功能外,还提供强大的聚合工具,如count、group 等,支持使用MapReduce 完成复杂的聚合任务。

(6)支持复制和数据恢复。MongoDB 支持主从复制机制,可以实现数据备份、故障恢复、读扩展等功能。而基于副本集的复制机制提供了自动故障恢复的功能,确保了集群数据不会丢失。

(7)使用高效的二进制数据存储,包括大型对象(如视频)。使用二进制格式存储,可以保存任何类型的数据对象。

(8)自动处理分片,以支持云计算层次的扩展。MongoDB 支持集群自动切分数据,对数据进行分片可以使集群存储更多的数据,实现更大的负载,也能保证存储的负载均衡。

(9)支持Perl、PHP、Java、C#、JavaScript、Ruby、C 和C++语言的驱动程序,MongoDB 提供了当前所有主流开发语言的数据库驱动包,开发人员使用任何一种主流开发语言都可以轻松编程,实现访问MongoDB 数据库。

(10)文件存储格式为BSON(JSON 的一种扩展)。BSON 是对二进制格式的JSON 的简称,BSON 支持文档和数组的嵌套。

(11)可以通过网络访问。可以通过网络远程访问MongoDB 数据库。

基本概念:

(1)文档

文档是 MongoDB 中数据的基本单位,类似于关系数据库中的行(但是比行复杂)。多个键及其关联的值有序地放在一起就构成了文档。不同的编程语言对文档的表示方法不同

{“foo”: 3 ,“greeting”:“hello,world”}

文档中的值不仅可以是双引号中的字符串,也可以是其他的数据类型,例如,整型、布尔型等,也可以是另外一个文档,即文档可以嵌套。文档中的键类型只能是字符串。

(2)集合

集合就是一组文档,类似于关系数据库中的表。集合是无模式的,集合中的文档可以是各式各样的。例如,{“hello,word”:“Mike”}和{“foo”: 3},它们的键不同,值的类型也不同,但是它们可以存放在同一个集合中,也就是不同模式的文档都可以放在同一个集合中。用户可以灵活选择。

可以使用“.”按照命名空间将集合划分为子集合。虽然子集合没有任何特殊的地方,但是使用子集合组织数据结构清晰,这也是MongoDB 推荐的方法。

(3)数据库

MongoDB 中多个文档组成集合,多个集合组成数据库。一个MongoDB 实例可以承载多个数据库。它们之间可以看作相互独立,每个数据库都有独立的权限控制。在磁盘上,不同的数据库存放在不同的文件中。MongoDB 中存在以下系统数据库。

● Admin 数据库:一个权限数据库,如果创建用户的时候将该用户添加到admin 数据库中,那么该用户就自动继承了所有数据库的权限。

● Local 数据库:这个数据库永远不会被负责,可以用来存储本地单台服务器的任意集合。

● Config 数据库:当MongoDB 使用分片模式时,config 数据库在内部使用,用于保存分片的信息


为什么要用它?

 特点:

它的特点是高性能、易部署、易使用,存储数据非常方便。主要功能特性有:

*面向集合存储,易存储对象类型的数据。

*模式自由。

*支持动态查询

*支持完全索引,包含内部对象。

*支持查询。

*支持复制和故障恢复。

*使用高效的二进制数据存储,包括大型对象(如视频等)。

*自动处理碎片,以支持云计算层次的扩展性。

*支持RUBYPYTHONJAVAC++PHPC#等多种语言。

*文件存储格式为BSON(一种JSON的扩展)。

*可通过网络访问。

就是,支持动态查询,存储快吧,还可以存一些大的文件,效率什么的,不知道,感觉还行。现在刚使用,就这种感觉。

原因:

所谓“面向集合”(Collection-Oriented),意思是数据被分组存储在数据集中,被称为一个集合(Collection)。每个集合在数据库中都有一个唯一的标识名,并且可以包含无限数目的文档。集合的概念类似关系型数据库(RDBMS)里的表(table),不同的是它不需要定义任何模式(schema)。Nytro MegaRAID技术中的闪存高速缓存算法,能够快速识别数据库内大数据集中的热数据,提供一致的性能改进。

模式自由(schema-free),意味着对于存储在mongodb数据库中的文件,我们不需要知道它的任何结构定义。如果需要的话,你完全可以把不同结构的文件存储在同一个数据库里。

存储在集合中的文档,被存储为键-值对的形式。键用于唯一标识一个文档,为字符串类型,而值则可以是各种复杂的文件类型。我们称这种存储形式为BSON(Binary Serialized Document Format)。 [3] 

[4]  MongoDB已经在多个站点部署,其主要场景如下:

1)网站实时数据处理。它非常适合实时的插入、更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。

2)缓存。由于性能很高,它适合作为信息基础设施的缓存层。在系统重启之后,由它搭建的持久化缓存层可以避免下层的数据源过载。

3)高伸缩性的场景。非常适合由数十或数百台服务器组成的数据库,它的路线图中已经包含对MapReduce引擎的内置支持。

不适用的场景如下:

1)要求高度事务性的系统。

2)传统的商业智能应用。

3)复杂的跨文档(表)级联查询。 

注意事项:

MongoDB服务端可运行在LinuxWindows或mac os x平台,支持32位和64位应用,默认端口为27017。推荐运行在64位平台,因为MongoDB在32位模式运行时支持的最大文件尺寸为2GB。 


怎么用?

一,安装篇

1.安装
https://www.mongodb.com/download-center?jmp=nav#community


2.安装之后我就放到”D盘“,改下文件夹名字为”mongodb“(data,etc,logs三个文件夹为后面自己创建的,稍后说明)。

创建 D:\mongdb\data\db  ①:启动之前,我们要给mongodb指定一个文件夹,这里取名为”db",用来存放mongodb的数据。
        D:\mongdb\data\log

3.开启服务
打开cmd命令行窗口,切换到D:\mongodb\bin 目录执行如下命令
mongod --dbpath D:\MongoDB\data
这时命令行窗口会打印一些启动信息,最后一行显示为如下信息时表示启动成功了.
这时在浏览器输入http://localhost:27017/可以看到显示信息
目前mongodb服务已经启动了,关闭这个cmd窗口,会自动关闭服务。
下次可以用同样的步骤重新开启服务。(不推荐)

4.开启本地服务
事实上每次通过命令行启动Mongo是痛苦的,因此我们需要建立一个永久性服务,这就需要我们把Mongo加入到Windows本地服务中去。继续回到cmd,执行(会创建一个存放日志的文件夹及日志文件,data文件夹路径为本机data的路径):
mongod.exe --logpath D:\mongodb\logs\mongodb.log --logappend --dbpath D:\mongodb\data --directoryperdb --serviceName MongoDB --install


服务创建完成之后,默认是停止状态,我们需要手动打开服务,用命令,net start MongoDB,开启服务。(如果不生效,也可以自己打开任务管理器,找到相关服务,手动打开。如图表示mongodb服务已启动)

二,基础入门篇

mongodb中有三元素:数据库,集合,文档,其中“集合”
就是对应关系数据库中的“表”,“文档”对应“行”。

 “增删查改“操作

我们再开一个cmd,输入mongo命令打开shell,其实这个shell就是mongodb的客户端,

同时也是一个js的编译器,默认连接的是“test”数据库。
 

 show dbs 查看当前的数据库 

 use databaseName 选库 

 show tables/collections 查看当前库下的collection 

如何创建库? 
Mongodb的库是隐式创建,你可以use 一个不存在的库 
然后在该库下创建collection,即可创建库 
db.createCollection(‘collectionName’) 


collection允许隐式创建 
Db.collectionName.insert(document); 

db.collectionName.drop() 
删除collection 

db.dropDatabase(); 
删除database

注意,这里,创建了库后,需要添加数据,才能查看自己新创建的库。

<1>  insert 操作

这里就取集合名为“person”,要注意的就是文档是一个json的扩展(Bson)形式。

db.person.insert({"name":"kack","age":20})
db.person.insert({"name":"joe","age":25})

<2> find 操作

我们将数据插入后,肯定是要find出来,不然插了也白插,这里要注意两点:① “_id": 这个字段是数据库默认给我们加的GUID,目的就是保证数据的唯一性。
② 严格的按照Bson的形式书写文档,不过也没关系,错误提示还是很强大的。


db.person.find()
查询所有


db.person.find({"name":joe})

<3> update操作
update方法的第一个参数为“查找的条件”,第二个参数为“更新的值"

db.person.update({"name":"joe"},{"name":"joe","age":"30"})

<4> remove操作
remove中如果不带参数将删除所有数据, ,在mongodb中是一个不可撤回的操作,小心。

三,细说增删查改

一: Insert操作
文档是采用“K-V”格式存储的,JSON里面Value

可能是“字符串”,可能是“数组”,又有可能是内嵌的一个JSON对象,相同的方式也适合于BSON。

常见的插入操作也就两种形式存在:“单条插入”和“批量插入”。

 ①  单条插入
mongo命令打开的是一个javascript shell。所以js的语法在这里面都行得通。

var single = ("name":"jack","password":"12345","age":20)
db.user.insert(single);

② 批量插入
由于mongodb中没有提供给shell的“批量插入方法”,没关系,各个语言的driver都打通

了跟mongodb内部的批量插入方法,因为该方法是不可或缺的,如果大家非要模拟下批量插入的话,可以自己写了for循环,里面就是insert。

二:Find操作

日常开发中,我们玩查询,玩的最多的也就是二类:      
 ①: >, >=, <, <=, !=, =。

 ②:And,OR,In,NotIn

mongodb里面都封装


<1>"$gt", "$gte", "$lt", "$lte", "$ne", "没有特殊关键字",这些跟上面是一一对应的,举几个例子。


        $gt:>

        $gte:>=

        $eq:        =

        $ne:        !=

        $lt:        <

        $lte:        <=

        $in:        in(后面的值为bson对象数组)

        $nin:        not in(后面的值为bson对象数组)

 

 

四,与spring-date - MongoRepository 结合篇


maven项目

1.配置
  

             <dependency>
                <groupId>org.springframework.data</groupId>
                <artifactId>spring-data-mongodb</artifactId>
                <version>1.10.1.RELEASE</version>
            </dependency>

2.配置Mongodb配置文件 MongoCOnfig.java 

package com.bbt.log.common.framework;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoClientFactoryBean;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import com.mongodb.Mongo;

// http://zoeminghong.github.io/2016/07/05/mongo20160705/
@Configuration
@EnableMongoRepositories(basePackages = "com.xiaoqiang.log.mongo.repository")
public class MongoConfig {
     
    // 域名 ip
    public static String MONGO_HOST = "127.0.0.1";
    // 所连的mongodb服务器
    public static String MONGO_DATABASE_NAME = "xiaoqiang";

    // 注册bean 
    @Bean
    public MongoClientFactoryBean mongo() {
        MongoClientFactoryBean mongo = new MongoClientFactoryBean();
        mongo.setHost("127.0.0.1");
        mongo.setPort(27017);
        // MongoCredential credential=MongoCredential.createCredential(env.getProperty("mongo.username"),
        // "OrdersDB",env.getProperty("mongo.password").toCharArray());
        // mongo.setCredentials(new MongoCredential[]{credential});
        return mongo;
    }

    // 注册bean MongoTempalte对象
    @Bean
    public MongoOperations mongoTemplate(Mongo mongo) {
        return new MongoTemplate(mongo, MONGO_DATABASE_NAME);
    }
}

 3.仓库集成

  


package com.xiaoqiang.log.client.event;
import java.util.Date;

/**
 * Created by xiaoqiang on 17/3/23.
 */
public class UserLoginEvent {

    private String sellerNick;


    public UserLoginEvent() {
        this.eventType = EventTypeEnum.USER_LOGIN.value();
    }

    public String getSellerNick() {
        return sellerNick;
    }

    public void setSellerNick(String sellerNick) {
        this.sellerNick = sellerNick;
    }

 
}

如果只是用简单的CRUD操作,则不需要添加其他的方法,MongoRepository提供的方法足够我们使用。
 

package com.xiaoqiang.log.mongo.repository;


import com.bbt.log.client.event.UserLoginEvent;
import org.springframework.data.mongodb.repository.MongoRepository;

public interface UserLoginRepository extends MongoRepository<UserLoginEvent, String> {
 

}

 我们打开这个MongoRepository仓库源码

/*
 * Copyright 2010-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.data.mongodb.repository;

import java.io.Serializable;
import java.util.List;

import org.springframework.data.domain.Example;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.QueryByExampleExecutor;

/**
 * Mongo specific {@link org.springframework.data.repository.Repository} interface.
 *
 * @author Oliver Gierke
 * @author Christoph Strobl
 * @author Thomas Darimont
 * @author Mark Paluch
 */
@NoRepositoryBean
public interface MongoRepository<T, ID extends Serializable>
		extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.CrudRepository#save(java.lang.Iterable)
	 */
	@Override
	<S extends T> List<S> save(Iterable<S> entites);

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.CrudRepository#findAll()
	 */
	@Override
	List<T> findAll();

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.PagingAndSortingRepository#findAll(org.springframework.data.domain.Sort)
	 */
	@Override
	List<T> findAll(Sort sort);

	/**
	 * Inserts the given entity. Assumes the instance to be new to be able to apply insertion optimizations. Use
	 * the returned instance for further operations as the save operation might have changed the entity instance
	 * completely. Prefer using {@link #save(Object)} instead to avoid the usage of store-specific API.
	 *
	 * @param entity must not be {@literal null}.
	 * @return the saved entity
	 * @since 1.7
	 */
	<S extends T> S insert(S entity);

	/**
	 * Inserts the given entities. Assumes the given entities to have not been persisted yet and thus will optimize the
	 * insert over a call to {@link #save(Iterable)}. Prefer using {@link #save(Iterable)} to avoid the usage of store
	 * specific API.
	 *
	 * @param entities must not be {@literal null}.
	 * @return the saved entities
	 * @since 1.7
	 */
	<S extends T> List<S> insert(Iterable<S> entities);

	/* 
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example)
	 */
	@Override
	<S extends T> List<S> findAll(Example<S> example);

	/* 
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example, org.springframework.data.domain.Sort)
	 */
	@Override
	<S extends T> List<S> findAll(Example<S> example, Sort sort);
}

 可以知道,已经提供了,基础的crud操作。

 

3.利用MongoRepository中的查询进行操作 
首先,在service层中,将PersonRepository注入到service类中

 (重要)java 操作mongoDB(DBobject,非spring data)

 DBCollection类:指定数据库中指定集合的实例,提供了增删改查等一系列操作。在关系型数据库中,对数据的增删改查操作是  建立在表的基础上的,在mongodb中是建立在集合的基础上进行的。

 DBObject接口:DBObject是键值的映射,因此,可以将DBObject的实现类作为查询的返回结果,也可以作为查询条件

 DBCursor:游标,返回结果的集合。

package com.bbt.log.service.impl;

import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.data.mongodb.core.MongoOperations;

import com.xiaoqiang.log.client.enums.LoginFromEnum;
import com.xiaoqiang.log.model.query.RecordBbtCustomerLogQuery;
import com.xiaoqiang.log.model.result.RecordBbtCustomerLogResultModel;
import com.xiaoqiang.log.service.RecordBbtCustomerLogService;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;

public class RecordBbtCustomerLogServiceImpl implements RecordBbtCustomerLogService {

	private Log LOG = LogFactory.getLog(RecordBbtCustomerLogServiceImpl.class);

	@Resource
	private MongoOperations mongoTemplate;

	@Override
	public RecordBbtCustomerLogResultModel queryUserLoginCount(RecordBbtCustomerLogQuery query) {
		RecordBbtCustomerLogResultModel recordBbtCustomerLogResultModel = new RecordBbtCustomerLogResultModel();
		recordBbtCustomerLogResultModel.setStatus(1);
		recordBbtCustomerLogResultModel.setMsg("请求处理成功");

		List dbCursor = null;
		DBObject dBObject = null;
		try {
			dBObject = new BasicDBObject(); // setup the query criteria 设置查询条件
			dBObject.put("lastLoginTime", (new BasicDBObject("$gte", query.getStartTime())).append("$lte", query.getEndTime()));
			dBObject.put("from", (new BasicDBObject("$eq", LoginFromEnum.PC_WEB.value())));
			dbCursor = mongoTemplate.getCollection("userLoginEvent").distinct("sellerNick", dBObject);
			if (null == dbCursor || dbCursor.isEmpty()) {
				recordBbtCustomerLogResultModel.setPcWebCount(0);
			} else {
				recordBbtCustomerLogResultModel.setPcWebCount(dbCursor.size());
			}

			dBObject.put("from", (new BasicDBObject("$eq", LoginFromEnum.PC_QN.value())));
			dbCursor = mongoTemplate.getCollection("userLoginEvent").distinct("sellerNick", dBObject);
			if (null == dbCursor || dbCursor.isEmpty()) {
				recordBbtCustomerLogResultModel.setPcQnCount(0);
			} else {
				recordBbtCustomerLogResultModel.setPcQnCount(dbCursor.size());
			}

			dBObject.put("from", (new BasicDBObject("$eq", LoginFromEnum.MOBILE_QN.value())));
			dbCursor = mongoTemplate.getCollection("userLoginEvent").distinct("sellerNick", dBObject);
			if (null == dbCursor || dbCursor.isEmpty()) {
				recordBbtCustomerLogResultModel.setMobileQnCount(0);
			} else {
				recordBbtCustomerLogResultModel.setMobileQnCount(dbCursor.size());
			}
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
			recordBbtCustomerLogResultModel.setStatus(0);
			recordBbtCustomerLogResultModel.setMsg("请求处理失败");
		}
		return recordBbtCustomerLogResultModel;
	}

}
// 4.查询所有的数据:
public List<Person> queryAll() throws Exception {
   return personRepository.findAll();
}

 

5.根据实体类中的属性进行查询: 

当需要根据实体类中的属性查询时,MongoRepository提供的方法已经不能满足,我们需要在PersonRepository仓库中定义方法,定义方法名的规则为:find + By + 属性名(首字母大写)

package com.xiaoqiang.log.mongo.repository;


import com.xiaoqiang.log.client.event.UserLoginEvent;
import org.springframework.data.mongodb.repository.MongoRepository;

public interface UserLoginRepository extends MongoRepository<UserLoginEvent, String> {

    // public List<UserLoginEvent> findBySellerNick(String sellerNick)

}

注意:

查询语句

db.getCollection('pageAccessEvent').find({"gmtCreate":{"$gte" : ISODate("2019-03-13T00:00:00.000Z"),"$lte" : ISODate("2019-03-13T23:59:59.591Z") }})

mongodb默认时间,是标准时间,查询的时候要加8个小时,任意的转换都是+8,均需要减8个小时,搞了一下午

多条查询

db.getCollection('userLoginEvent').find({
    "sellerNick":"tb979768_44",
    "loginTime":{"$gte" : ISODate("2019-09-18T00:00:00.000Z"),"$lte" : ISODate("2019-09-18T23:59:59.591Z") }
    })
db.getCollection('userChargeEvent').find({ "sellerNick":"tb979768_44"}).sort({"_id":-1}).limit(1)

   倒序查询 最后一条

总结:到这里,基本上,mongodb的使用,安装,集成java,等等,都可以了。 后续的再说。

 参考资料:

 https://blog.youkuaiyun.com/novodexx/article/details/79329431

 

 

{
	"collection": "MetricModuleEvent",
	"aggregate": [
		{
			"$match": {
				"dateNo": {{ dateNo }}
			}
		},
		{
			"$lookup": {
				"from": "pageMappingModuleEvent",
				"localField": "page",
				"foreignField": "url",
				"as": "a"
			}
		},
		{
			"$unwind": "$a"
		},
		{
			"$addFields": {
				"name": "$a.module"
			}
		},
		{
			"$project": {
				"dateNo": 1,
				"pv": 1,
				"uv": 1,
				"name": 1,
				"_id": 0,
				"page": 1
			}
		}
	]
}

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值