秀才


  • Home

  • About

  • Tags

  • Archives

  • Search

strings

Posted on 2018-09-25 | Visitors:

实现随机数

1
2
3
4
5
6
7
8
9
10
11
12
13
func CreateRandom(strLen int) string {
strRandom := "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM"
bytes := []byte(strRandom)
strByte := []byte{}
// 需要一个随机种子(torrent),不然每次都是一样的随机数
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < strLen; i++ {
subNum := r.Intn(len(bytes))
sep := bytes[subNum]
strByte = append(strByte, sep)
}
return string(strByte)
}

MD5加密

1
2
3
4
5
func Md5(str string) string {
m := md5.New()
m.Write([]byte(str))
return hex.EncodeToString(m.Sum(nil))
}

docker-compose

Posted on 2018-09-25 | Visitors:

安装

最为推荐:
$ sudo pip install -U docker-compose
之后,可以添加 bash 补全命令:
curl -L https://raw.githubusercontent.com/docker/compose/1.2.0/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose

命令说明

基本的使用格式是

1
docker-compose [options] [COMMAND] [ARGS...]

选项:

1
2
3
4
--verbose 输出更多调试信息。
--version 打印版本并退出。
-f, --file FILE 使用特定的 compose 模板文件,默认为 docker-compose.yml。
-p, --project-name NAME 指定项目名称,默认使用目录名称。

命令

build

构建或重新构建服务。
服务一旦构建后,将会带上一个标记名,例如 web_db。
可以随时在项目目录下运行 docker-compose build 来重新构建服务。

help

获得一个命令的帮助。

kill

通过发送 SIGKILL 信号来强制停止服务容器。支持通过参数来指定发送的信号,例如

1
$ docker-compose kill -s SIGINT

logs

查看服务的输出。

port

打印绑定的公共端口。

ps

列出所有容器。

pull

拉取服务镜像。

rm

删除停止的服务容器。

run

在一个服务上执行一个命令。
例如:

1
$ docker-compose run ubuntu ping docker.com

将会启动一个 ubuntu 服务,执行 ping docker.com 命令。
默认情况下,所有关联的服务将会自动被启动,除非这些服务已经在运行中。
该命令类似启动容器后运行指定的命令,相关卷、链接等等都将会按照期望创建。
两个不同点:

  • 给定命令将会覆盖原有的自动运行命令;
  • 不会自动创建端口,以避免冲突。
    如果不希望自动启动关联的容器,可以使用 –no-deps 选项,例如
    1
    2
    $ docker-compose run --no-deps web python manage.py shell
    将不会启动 web 容器所关联的其它容器。

scale

设置同一个服务运行的容器个数。
通过 service=num 的参数来设置数量。例如:

1
$ docker-compose scale web=2 worker=3

start

启动一个已经存在的服务容器。

stop

停止一个已经运行的容器,但不删除它。通过 docker-compose start 可以再次启动这些容器。

up

构建,(重新)创建,启动,链接一个服务相关的容器。
链接的服务都将会启动,除非他们已经运行。
默认情况, docker-compose up 将会整合所有容器的输出,并且退出时,所有容器将会停止。
如果使用 docker-compose up -d ,将会在后台启动并运行所有的容器。
默认情况,如果该服务的容器已经存在, docker-compose up 将会停止并尝试重新创建他们(保持使用 volumes-from 挂载的卷),以保证 docker-compose.yml 的修改生效。如果你不想容器被停止并重新创建,可以使用 docker-compose up --no-recreate。如果需要的话,这样将会启动已经停止的容器。


YAML模板

image

指定为镜像名称或镜像 ID。如果镜像在本地不存在,Compose 将会尝试拉去这个镜像。
例如:

1
2
3
image: ubuntu
image: orchardup/postgresql
image: a4bc65fd

build

指定 Dockerfile 所在文件夹的路径。 Compose 将会利用它自动构建这个镜像,然后使用这个镜像。

1
build: /path/to/build/dir

command

覆盖容器启动后默认执行的命令。

1
command: bundle exec thin -p 3000

links

链接到其它服务中的容器。使用服务名称(同时作为别名)或服务名称:服务别名 (SERVICE:ALIAS) 格式都可以。

1
2
3
4
links:
- db
- db:database
- redis

使用的别名将会自动在服务容器中的 /etc/hosts 里创建。例如:

1
2
3
172.17.2.186  db
172.17.2.186 database
172.17.2.187 redis

相应的环境变量也将被创建。

external_links

链接到 docker-compose.yml 外部的容器,甚至 并非 Compose 管理的容器。参数格式跟 links 类似。

1
2
3
4
external_links:
- redis_1
- project_db_1:mysql
- project_db_1:postgresql

ports

暴露端口信息。
使用宿主:容器 (HOST:CONTAINER)格式或者仅仅指定容器的端口(宿主将会随机选择端口)都可以。

1
2
3
4
5
ports:
- "3000"
- "8000:8000"
- "49100:22"
- "127.0.0.1:8001:8001"

注:当使用 HOST:CONTAINER 格式来映射端口时,如果你使用的容器端口小于 60 你可能会得到错误得结果,因为 YAML 将会解析 xx:yy 这种数字格式为 60 进制。所以建议采用字符串格式。

expose

暴露端口,但不映射到宿主机,只被连接的服务访问。
仅可以指定内部端口为参数

1
2
3
expose:
- "3000"
- "8000"

volumes

卷挂载路径设置。可以设置宿主机路径 (HOST:CONTAINER) 或加上访问模式 (HOST:CONTAINER:ro)。

1
2
3
4
5
volumes:
- /var/lib/mysql
- cache/:/tmp/cache
- ~/configs:/etc/configs/:ro
volumes_from

从另一个服务或容器挂载它的所有卷。

1
2
3
volumes_from:
- service_name
- container_name

environment

设置环境变量。你可以使用数组或字典两种格式。
只给定名称的变量会自动获取它在 Compose 主机上的值,可以用来防止泄露不必要的数据。

1
2
3
4
5
6
environment:
RACK_ENV: development
SESSION_SECRET:
environment:
- RACK_ENV=development
- SESSION_SECRET

env_file

从文件中获取环境变量,可以为单独的文件路径或列表。
如果通过 docker-compose -f FILE 指定了模板文件,则 env_file 中路径会基于模板文件路径。
如果有变量名称与 environment 指令冲突,则以后者为准。

1
2
3
4
5
6
env_file: .env

env_file:
- ./common.env
- ./apps/web.env
- /opt/secrets.env

环境变量文件中每一行必须符合格式,支持 # 开头的注释行。

1
2
#  common.env: Set Rails/Rack environment
RACK_ENV=development

extends

基于已有的服务进行扩展。例如我们已经有了一个 webapp 服务,模板文件为 common.yml。

1
2
3
4
5
6
#  common.yml
webapp:
build: ./webapp
environment:
- DEBUG=false
- SEND_EMAILS=false

编写一个新的 development.yml 文件,使用 common.yml 中的 webapp 服务进行扩展。

1
2
3
4
5
6
7
8
9
10
11
12
13
#  development.yml
web:
extends:
file: common.yml
service: webapp
ports:
- "8000:8000"
links:
- db
environment:
- DEBUG=true
db:
image: postgres

后者会自动继承 common.yml 中的 webapp 服务及相关环节变量。

net

设置网络模式。使用和 docker client 的 –net 参数一样的值。

1
2
3
4
net: "bridge"
net: "none"
net: "container:[name or id]"
net: "host"

pid

跟主机系统共享进程命名空间。打开该选项的容器可以相互通过进程 ID 来访问和操作。

1
pid: "host"

dns

配置 DNS 服务器。可以是一个值,也可以是一个列表。

1
2
3
4
dns: 8.8.8.8
dns:
- 8.8.8.8
- 9.9.9.9

cap_add, cap_drop

添加或放弃容器的 Linux 能力(Capabiliity)。

1
2
3
4
5
6
cap_add:
- ALL

cap_drop:
- NET_ADMIN
- SYS_ADMIN

dns_search

配置 DNS 搜索域。可以是一个值,也可以是一个列表。

1
2
3
4
dns_search: example.com
dns_search:
- domain1.example.com
- domain2.example.com

working_dir, entrypoint, user, hostname, domainname, mem_limit, privileged, restart, stdin_open, tty, cpu_shares

这些都是和 docker run 支持的选项类似。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cpu_shares: 73

working_dir: /code
entrypoint: /code/entrypoint.sh
user: postgresql

hostname: foo
domainname: foo.com

mem_limit: 1000000000
privileged: true

restart: always

stdin_open: true
tty: true

常用命令

Posted on 2018-09-25 | Visitors:

最好是查看docker文档


查看docker信息(version、info)

1
2
3
4
5
# 查看docker版本  
docker version

# 显示docker系统的信息
docker info

对image的操作(search、pull、images、rmi、history)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 检索image  
$docker search image_name

# 下载image
$docker pull image_name

# 列出镜像列表; -a, --all=false Show all images; --no-trunc=false Don't truncate output; -q, --quiet=false Only show numeric IDs
$docker images

# 删除一个或者多个镜像; -f, --force=false Force; --no-prune=false Do not delete untagged parents
$docker rmi image_name

# 显示一个镜像的历史; --no-trunc=false Don't truncate output; -q, --quiet=false Only show numeric IDs
$docker history image_name

启动容器(run)

1
2
3
4
5
6
7
8
$docker run image_name echo "hello word"  

# 交互式进入容器中
$docker run -i -t image_name /bin/bash


# 在容器中安装新的程序
$docker run image_name apt-get install -y app_name

查看容器(ps)

1
2
3
4
5
6
# 列出当前所有正在运行的container  
$docker ps
# 列出所有的container
$docker ps -a
# 列出最近一次启动的container
$docker ps -l

保存对容器的修改(commit)

1
2
# 保存对容器的修改; -a, --author="" Author; -m, --message="" Commit message  
$docker commit ID new_image_name

对容器的操作(rm、stop、start、kill、logs、diff、top、cp、restart、attach)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 删除所有容器  
$docker rm `docker ps -a -q`

# 删除单个容器; -f, --force=false; -l, --link=false Remove the specified link and not the underlying container; -v, --volumes=false Remove the volumes associated to the container
$docker rm Name/ID

# 停止、启动、杀死一个容器
$docker stop Name/ID
$docker start Name/ID
$docker kill Name/ID

# 从一个容器中取日志; -f, --follow=false Follow log output; -t, --timestamps=false Show timestamps
$docker logs Name/ID

# 列出一个容器里面被改变的文件或者目录,list列表会显示出三种事件,A 增加的,D 删除的,C 被改变的
$docker diff Name/ID

# 显示一个运行的容器里面的进程信息
$docker top Name/ID

# 从容器里面拷贝文件/目录到本地一个路径
$docker cp Name:/container_path to_path
$docker cp ID:/container_path to_path

# 重启一个正在运行的容器; -t, --time=10 Number of seconds to try to stop for before killing the container, Default=10
$docker restart Name/ID

# 附加到一个运行的容器上面; --no-stdin=false Do not attach stdin; --sig-proxy=true Proxify all received signal to the process
$docker attach ID

保存和加载镜像(save、load)

1
2
3
4
5
6
7
8
$docker save image_name -o file_path  
# 加载一个tar包格式的镜像; -i, --input="" Read from a tar archive file
$docker load -i file_path

# 机器a
$docker save image_name > /home/save.tar
# 使用scp将save.tar拷到机器b上,然后:
$docker load < /home/save.tar

登录registry server(login)

1
2
# 登陆registry server; -e, --email="" Email; -p, --password="" Password; -u, --username="" Username  
$docker login

发布image(push)

1
2
# 发布docker镜像  
$docker push new_image_name

根据Dockerfile 构建出一个容器(build)

1
2
3
4
5
6
#build  
--no-cache=false Do not use cache when building the image
-q, --quiet=false Suppress the verbose output generated by the containers
--rm=true Remove intermediate containers after a successful build
-t, --tag="" Repository name (and optionally a tag) to be applied to the resulting image in case of success
$docker build -t image_name Dockerfile_path

mgo

Posted on 2018-09-25 | Visitors:

mongodb客户端的golang实现
mgo很有可能作为golang的标准库
mgo文档

连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package database

import (
"full_text_search/config"
"gopkg.in/mgo.v2"
)

var Session *mgo.Session

// 简单实现单例,只创建一个session
func init() {
if Session == nil {
var err error
Session, err = mgo.Dial(config.MongoDB.Host + ":" + config.MongoDB.Port)
if err != nil {
panic("连接mongodb失败,原因:" + err.Error())
}
}
}

func Collection(collectionName string, f func(collection *mgo.Collection)) (err error) {
// mgo内部实现了连接池,通过clone获取连接
session := Session.Clone()
defer func() {
session.Close()
if err := recover(); err != nil {
return
}
}()
collection := session.DB(config.MongoDB.Database).C(collectionName)
f(collection)
return
}

登录

1
2
3
4
5
6
7
8
Session, err = mgo.Dial(config.MongoDB.Host + ":" + config.MongoDB.Port)
if err != nil {
panic("连接mongodb失败,原因:" + err.Error())
}
err = Session.DB("admin").Login(config.MongoDB.User, config.MongoDB.Password)
if err != nil{
panic("登录mongodb失败,原因:" + err.Error())
}

增删改查

上述是建立连接,并执行操作

insert

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
type d struct {
X int
Y int
Z int
}
database.Collection("user", func(collection *mgo.Collection) {
var insertDatas = []interface{}{
d{6, 6, 6},
d{7, 6, 6},
d{8, 6, 6},
}
var insertData = d{9, 9, 9}
//插入单条
collection.Insert(insertData)
//插入多条
collection.Insert(insertDatas...)
})

select

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
type d struct {
X int
Y int
Z int
}

// 为了代码的可读性,没有验证错误error
database.Collection("user", func(collection *mgo.Collection) {
var resDatas []d
var resData d
query := collection.Find(bson.M{"x": 1})
//统计数目
count, _ := query.Count()
//链式操作,类似函数式编程
query = query.Sort("y").Skip(1).Limit(2)
//查询所有
query.All(&resDatas)
//查询第一个
query.One(&resData)
fmt.Println(resDatas, resData, count)
})

delete

1
2
3
4
// 为了代码的可读性,没有验证错误error
database.Collection("user", func(collection *mgo.Collection) {
collection.Remove(bson.M{"x": 1})
})

update

  • 修改第一条,修改此条全部内容

    1
    2
    3
    4
    5
    6
    //struct 的键需要大写
    collection.Update(bson.M{"x": 3}, struct {
    X int
    Y int
    Z int
    }{3, 4, 5})
  • 修改第一条,修改此条部分内容

    1
    collection.Update(bson.M{"x": 0}, bson.M{"$set": bson.M{"y": 1}})
  • 修改多条,只能修改每一条的部分内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    changeLog, err := collection.UpdateAll(bson.M{"x": 6}, bson.M{"$set": bson.M{"y": 1}})
    if err != nil {
    fmt.Println(err.Error())
    }
    fmt.Println("Matched:", changeLog.Matched)
    fmt.Println("Removed:", changeLog.Removed)
    fmt.Println("Updated:", changeLog.Updated)
    fmt.Println("UpsertedId:", changeLog.UpsertedId)
    // 结果
    > go run test.go
    Matched: 2
    Removed: 0
    Updated: 2
    UpsertedId: <nil>

pdf处理

Posted on 2017-09-06 | Visitors:

简介

PDFtk 是什么?我觉得官网的一句话解释得很好。

If PDF is electronic paper, then PDFtk is an electronic staple-remover, hole-punch, binder, secret-decoder-ring, and X-Ray-glasses. PDFtk is a simple tool for doing everyday things with PDF documents.

其官方网站为:
官网

PDFtk 目前分为三个版本:

  • PDFtk Server:
    命令行工具。支持 windows、Linux、Mac。
  • PDFtk Free:
    图形界面基础免费版;仅限 windows 用户;功能仅限于 PDF 合并和分割;
  • PDFtk Pro:
    图形界面专业收费版;仅限 windows 用户,可以对 PDF 文档进行合并、分割、旋转、加水印、加邮戳、加密。

对于 Linux 用户,唯一的选择是免费的 PDFtk Server,其功能与收费 PDFtk Pro 完全相同,只是没有 GUI 而已。作者还是很厚道的。

Linux 的各个发行版的官方源中基本都有该软件,直接 apt-get 或者 yum 安装即可。

功能

合并 PDF;
分割 PDF 页面;
旋转 PDF 文档或页面;
PDF 解密;(不是破解)
PDF 加密;
用 X/FDF 填写 PDF 表格;
从 PDF 表格中生成 PDF Data Stencils;
加背景水印或前景印章;
报告 PDF Metrics,书签和元数据;
增加 / 更新 PDF 书签或元数据;
给 PDF 页面或文档加附件;
解压 PDF 附件;
分解 PDF 文档为多个单页;
解压缩和重压缩页面流;
修复受损的 PDF 文档;
这功能完全可以与 Adobe Acrobat 相媲美了,更重要的是 PDFtk 支持 Linux 且完全免费。(个人用户免费,若用于商业用途需付费)。

用法示例

具体选项看这里:

具体选项

下面给出一些常见的例子。例子原文

扫描一本书,odd.pdf 为书的全部奇数页,even.pdf 为书的全部偶数页,下面的命令可以将两个 pdf 合并成页码正常的书:

1
pdftk A=odd.pdf B=even.pdf shuffle A B output collated.pdf

如果 odd.pdf 是逆序的:

1
pdftk A=odd.pdf B=even.pdf shuffle Aend-1 B output collated.pdf

加密 PDF:

1
pdftk secured.pdf input_pw foopass output unsecured.pdf

PDF 128 位加密,保留全部权限:

1
pdftk 1.pdf output 1.128.pdf owner_pw foopass

PDF 128 位加密,保留全部权限,打开文档需输入密码 “baz”:

1
pdftk 1.pdf output 1.128.pdf owner_pw foo user_pw baz

PDF 128 位加密,打开文档需输入密码 “baz”,保留打印之外的其他权限:

1
pdftk 1.pdf output 1.128.pdf owner_pw foo user_pw baz allow printing

合并 in1.pdf 和 in2.pdf 到新 PDF 中:

1
pdftk in1.pdf in2.pdf cat output out1.pdf

或(使用句柄):

1
pdftk A=in1.pdf B=in2.pdf cat A B output out1.pdf

或(使用通配符):

1
pdftk *.pdf cat output combined.pdf

去除 in1.pdf 中的第 13 页,并创建 out1.pdf:

1
pdftk in.pdf cat 1-12 14-end output out1.pdf

或

1
pdftk A=in1.pdf cat A1-12 A14-end output out1.pdf

对输出进行 40 位加密,撤销所有权限,设置 owner 密码为 foopass:

1
pdftk 1.pdf 2.pdf cat output 3.pdf encrypt_40bit owner_pw foopass

合并两个文件,其中一个需要被加密。对输出不加密:

1
pdftk A=secured.pdf 2.pdf input_pw A=foopass cat output 3.pdf

解压 PDF 页面流,然后就可以在文本编辑器中编辑 PDF 文件:

1
pdftk doc.pdf output doc.unc.pdf uncompress

压缩 PDF:

1
pdftk mydoc.pdf output mydoc.clear.pdf compress

修复破损的 PDF:

1
pdftk broken.pdf output fixed.pdf

将一个 PDF 文档分割成一页一个文档:

1
pdftk in.pdf burst

将一个 PDF 文档分割成一页一个文档,并加密,允许低质量的打印:

1
pdftk in.pdf burst owner_pw foopass allow DegradedPrinting

获取 PDF 问的元数据和书签信息:

1
pdftk in.pdf dump_data output report.txt

将 PDF 第一页顺时针旋转 90 度:

1
pdftk in.pdf cat 1east 2-end output out.pdf

将整个 PDF 文档旋转 180 度:

1
pdftk in.pdf cat 1-endsouth output out.pdf

shell

Posted on 2017-08-27 | Visitors:

判断命令是否执行成功

1
2
3
4
5
6
7
if [[ $? -eq 0 ]];then A else b;fi
# 或
if [ $? -eq 0 ];then
命令正确的分支
else
命令失败的分支
fi

在脚本中执行其他脚本

  • fork ( /directory/script.sh):

    如果shell中包含执行命令,那么子命令并不影响父级的命令,在子命令执行完后再执行父级命令。子级的环境变量不会影响到父级。
    fork是最普通的, 就是直接在脚本里面用/directory/script.sh来调用script.sh这个脚本.
    运行的时候开一个sub-shell执行调用的脚本,sub-shell执行的时候, parent-shell还在。
    sub-shell执行完毕后返回parent-shell. sub-shell从parent-shell继承环境变量.但是sub-shell中的环境变量不会带回parent-shell

  • exec (exec /directory/script.sh):

    执行子级的命令后,不再执行父级命令。
    exec与fork不同,不需要新开一个sub-shell来执行被调用的脚本. 被调用的脚本与父脚本在同一个shell内执行。但是使用exec调用一个新脚本以后, 父脚本中exec行之后的内容就不会再执行了。这是exec和source的区别

  • source (source /directory/script.sh):

    执行子级命令后继续执行父级命令,同时子级设置的环境变量会影响到父级的环境变量。
    与fork的区别是不新开一个sub-shell来执行被调用的脚本,而是在同一个shell中执行. 所以被调用的脚本中声明的变量和环境变量, 都可以在主脚本中得到和使用.

    获取时间

    1
    2
    file_name="`date +%y%m%d`.sql"
    # 结果:170109.sql

参数

1
2
# 将参数赋值给file_name变量,注意=两边不能有空格
file_name=$1

vim

Posted on 2017-08-05 | Visitors:

移动光标

  • ctrl+b: 前移一个字符(backward)
  • ctrl+f: 后移一个字符(forward)
  • alt+<-: 前移一个单词
  • alt+->: 后移一个单词
  • ctrl+a: 移到行首(a是首字母)
  • ctrl+e: 移到行尾(end)
  • ctrl+x: 行首到当前光标替换

编辑命令

  • alt+.: 粘帖最后一次命令最后的参数(通常用于mkdir long-long-dir后, cd配合着alt+.)
  • alt+d: 删除当前光标到临近右边单词开始(delete)
  • ctrl+w: 删除当前光标到临近左边单词结束(word)
  • ctrl+h: 删除光标前一个字符(相当于backspace)
  • ctrl+d: 删除光标后一个字符(相当于delete)
  • ctrl+u: 删除光标左边所有
  • ctrl+k: 删除光标右边所有
  • ctrl+l: 清屏
  • ctrl+shift+c: 复制(相当于鼠标左键拖拽)
  • ctrl+shift+v: 粘贴(相当于鼠标中键)

其它

  • ctrl+n: 下一条命令
  • ctrl+p: 上一条命令
  • alt+n: 下一条命令(例如输入ls, 然后按’alt+n’, 就会找到历史记录下的ls命令)
  • alt+p: 上一条命令(跟alt+n相似)
  • shift+PageUp: 向上翻页
  • shift+PageDown: 向下翻页
  • ctrl+r: 进入历史查找命令记录, 输入关键字。 多次按返回下一个匹配项

zsh

  • d: 列出以前的打开的命令
  • j: jump到以前某个目录,模糊匹配

Vim

移动光标

  • b: 向前移动一个单词
  • w: 向后移动一个单词

删除

  • dw: 从当前光标开始删除到下一个单词头
  • de: 从当前光标开始删除到单词尾

mongo聚合

Posted on 2017-06-08 | Visitors:

分组统计

shell语法

根据等级分组统计

1
> db.users.aggregate([{"$group":{"_id":"bookLevel", "count":{"$sum":1}}}])

根据引导分组统计

1
> db.users.aggregate([{"$group":{"_id":{"guide":"$guide", "guideTwo":"$guideTwo"}, "count":{"$sum":1}}}])

mgo语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// LevelCount 用户等级分布
type LevelCount struct {
Level int `bson:"_id"`
Count int `bson:"count"`
}
var counts []LevelCount
mongoInstance := db.GetInstance()
defer mongoInstance.Close()
collection := mongoInstance.GetCollection(UsersKey)
m := []bson.M{
{"$group": bson.M{"_id": "$bookLevel", "count": bson.M{"$sum": 1}}},
}
err = collection.Pipe(m).All(&counts)
if err != nil {
return
}

CRUD操作

Posted on 2017-04-29 | Visitors:

insert

  • 正常插入:

    1
    2
    > db.user.insert({x:1,y:2,z:3})
    WriteResult({ "nInserted" : 1 })
  • 循环插入

    1
    2
    > for(var i=1;i<100;i++) db.user.insert({x:i, y:i*10, z:i*100})
    WriteResult({ "nInserted" : 1 })

update

  • 整个更新

    1
    2
    3
    4
    5
    6
    7
    8
    > db.user.find()
    { "_id" : ObjectId("58d0d844bae387d0c1e8d870"), "x" : 1, "y" : 2 }
    { "_id" : ObjectId("58d0d84ebae387d0c1e8d871"), "x" : 2, "y" : 3 }
    > db.user.update({x:1},{x:999})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.user.find()
    { "_id" : ObjectId("58d0d844bae387d0c1e8d870"), "x" : 999 }
    { "_id" : ObjectId("58d0d84ebae387d0c1e8d871"), "x" : 2, "y" : 3 }
  • 部分更新
    使用$set操作符

    1
    2
    3
    4
    5
    6
    7
    8
    > db.user.find()
    { "_id" : ObjectId("58d0d844bae387d0c1e8d870"), "x" : 999 }
    { "_id" : ObjectId("58d0d84ebae387d0c1e8d871"), "x" : 2, "y" : 3 }
    > db.user.update({x:2},{$set:{x:999}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.user.find()
    { "_id" : ObjectId("58d0d844bae387d0c1e8d870"), "x" : 999 }
    { "_id" : ObjectId("58d0d84ebae387d0c1e8d871"), "x" : 999, "y" : 3 }
  • 不存在则创建

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    > db.user.find({x:1})
    > db.user.update({x:1},{x:2},true)
    WriteResult({
    "nMatched" : 0,
    "nUpserted" : 1,
    "nModified" : 0,
    "_id" : ObjectId("58d0da6e34123eac45d857ac")
    })
    > db.user.find()
    { "_id" : ObjectId("58d0d844bae387d0c1e8d870"), "x" : 999 }
    { "_id" : ObjectId("58d0d84ebae387d0c1e8d871"), "x" : 999, "y" : 3 }
    { "_id" : ObjectId("58d0da6e34123eac45d857ac"), "x" : 2 }
  • 更新多条
    mongodb默认是更新一条,据说是为了防止一时大意,
    而且更新多条不允许更新整个,只能使用$set关键字

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    > db.user.find()
    { "_id" : ObjectId("58d0dde9bae387d0c1e8d873"), "x" : 1, "y" : 2, "z" : 1 }
    { "_id" : ObjectId("58d0ddeabae387d0c1e8d874"), "x" : 1, "y" : 1, "z" : 1 }
    { "_id" : ObjectId("58d0ddebbae387d0c1e8d875"), "x" : 1, "y" : 1, "z" : 1 }
    > db.user.update({x:1},{$set:{y:2}},false,true)
    WriteResult({ "nMatched" : 3, "nUpserted" : 0, "nModified" : 2 })
    > db.user.find()
    { "_id" : ObjectId("58d0dde9bae387d0c1e8d873"), "x" : 1, "y" : 2, "z" : 1 }
    { "_id" : ObjectId("58d0ddeabae387d0c1e8d874"), "x" : 1, "y" : 2, "z" : 1 }
    { "_id" : ObjectId("58d0ddebbae387d0c1e8d875"), "x" : 1, "y" : 2, "z" : 1 }

remove

  • 删除某个collection所有内容

    1
    2
    > db.user.remove({})
    WriteResult({ "nRemoved" : 102 })
  • 删除某个

    1
    2
    > db.user.remove({x:3})
    WriteResult({ "nRemoved" : 1 })

find

  • 查找所有

    1
    2
    3
    4
    > db.user.find()
    { "_id" : ObjectId("58d0cebcbae387d0c1e8d80a"), "username" : "zhangsan" }
    { "_id" : ObjectId("58d0d36abae387d0c1e8d80b"), "x" : 1, "y" : 2, "z" : 3 }
    { "_id" : ObjectId("58d0d37dbae387d0c1e8d80c"), "x" : 1, "y" : 2, "z" : 3 }
  • 有条件查找

    1
    2
    3
    > db.user.find({x:1})
    { "_id" : ObjectId("58d0d36abae387d0c1e8d80b"), "x" : 1, "y" : 2, "z" : 3 }
    { "_id" : ObjectId("58d0d37dbae387d0c1e8d80c"), "x" : 1, "y" : 2, "z" : 3 }
  • 查找总数目

    1
    2
    > db.user.find().count()
    102
  • 分页,排序

    1
    2
    3
    4
    > db.user.find().skip(5).limit(3).sort({x:1})
    { "_id" : ObjectId("58d0d453bae387d0c1e8d80f"), "x" : 3, "y" : 30, "z" : 300 }
    { "_id" : ObjectId("58d0d453bae387d0c1e8d810"), "x" : 4, "y" : 40, "z" : 400 }
    { "_id" : ObjectId("58d0d453bae387d0c1e8d811"), "x" : 5, "y" : 50, "z" : 500 }

auth认证

Posted on 2017-04-25 | Visitors:

以auth认证方式启动

  • 可以在config文件中加一项:

    1
    auth: true
  • 可以在命令行中,添加一个option,--auth

但是,如果mongodb中没有用户,认证是没有意义的。

创建用户

  • 选择库

    1
    2
    // 用户的存储也是基于库的。管理员用户的话,需要在admin中创建。创建的第一个用户即为管理员用户
    > use admin
  • 创建管理员用户

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    db.createUser({
    user:"root",
    pwd:"root",
    roles:[
    {
    role:"userAdminAnyDatabase",
    db:"admin"
    }
    ]
    })
  • 创建普通用户

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    db.createUser({
    user:"user1",
    pwd:"pwd1",
    roles:[
    {
    role:"readWrite",
    db:"db1"
    }
    ]
    })

登录

方式1

1
2
3
4
5
// user所存储的库
> use admin
> db.auth(username, password)
// 返回原数据库
> use blog

方式2

1
> mongo --host ip:port -u 用户 -p 密码 --authenticationDatabase admin

mongodb配置文件相关参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#数据库数据存放目录
dbpath=/usr/local/mongodb304/data
#数据库日志存放目录
logpath=/usr/local/mongodb304/logs/mongodb.log
#以追加的方式记录日志
logappend = true
#端口号 默认为27017
port=27017
#以后台方式运行进程
fork=true
#开启用户认证
auth=true
#关闭http接口,默认关闭http端口访问
nohttpinterface=true
#mongodb所绑定的ip地址
bind_ip = 127.0.0.1,192.168.1.140
#启用日志文件,默认启用
journal=true
#这个选项可以过滤掉一些无用的日志信息,若需要调试使用请设置为false
quiet=true
1…567

chimps

63 posts
32 tags
RSS
© 京ICP备19001740号-1 2020 chimps
Powered by Hexo
|
Theme — NexT.Gemini v5.1.4