Win10下 Java环境变量配置(转)

首先,你应该已经安装了 Java 的 JDK 了(如果没有安装JDK,请跳转到此网址:http://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html)

笔者安装的是 jdk-8u91-windows-x64

接下来主要讲怎么配置 Java 的环境变量,也是为了以后哪天自己忘记了做个备份

(注:win10的Java环境变量配置和其他的windows版本稍有不同)

在电脑桌面 右键点击 “此电脑”的“属性”选项

选择“高级系统设置”选项

点击下面的“环境变量”选项

接下来就是具体的配置过程:

点击“系统变量”下面的”新建“选项

在”变量名“处填上”Java_Home“

”变量值“为JDK安装路径,笔者的路径是”D:\Program Files\Java\jdk1.8.0_91“

点击”确定“选项

在”系统变量“中找到”Path“

选中”Path“点击”编辑“选项

选择右边的“编辑文本”,将引号里面的全部复制“%Java_Home%\bin;%Java_Home%\jre\bin;”,到“变量值”栏的最前面,“确定”

在“系统变量”栏,“新建”,“变量名”为“CLASSPATH”,“变量值”为“.;%Java_Home%\bin;%Java_Home%\lib\dt.jar;%Java_Home%\lib\tools.jar”,“确定”

点击“环境变量”最下面的“确定”选项

回到电脑桌面,按快捷键“Win+R”,输入“cmd”

检查Java环境是否配置成功

输入”java”

输入”javac”

输入”java -version”

如果上面的三幅图都看见了,恭喜,环境变量配置好了!

linux screen 命令详解

一、背景

系统管理员经常需要SSH 或者telent 远程登录到Linux 服务器,经常运行一些需要很长时间才能完成的任务,比如系统备份、ftp 传输等等。通常情况下我们都是为每一个这样的任务开一个远程终端窗口,因为它们执行的时间太长了。必须等待它们执行完毕,在此期间不能关掉窗口或者断开连接,否则这个任务就会被杀掉,一切半途而废了。

二、简介

GNU Screen是一款由GNU计划开发的用于命令行终端切换的自由软件。用户可以通过该软件同时连接多个本地或远程的命令行会话,并在其间自由切换。

GNU Screen可以看作是窗口管理器的命令行界面版本。它提供了统一的管理多个会话的界面和相应的功能。

  • 会话恢复

只要Screen本身没有终止,在其内部运行的会话都可以恢复。这一点对于远程登录的用户特别有用——即使网络连接中断,用户也不会失去对已经打开的命令行会话的控制。只要再次登录到主机上执行screen -r就可以恢复会话的运行。同样在暂时离开的时候,也可以执行分离命令detach,在保证里面的程序正常运行的情况下让Screen挂起(切换到后台)。这一点和图形界面下的VNC很相似。

  • 多窗口

在Screen环境下,所有的会话都独立的运行,并拥有各自的编号、输入、输出和窗口缓存。用户可以通过快捷键在不同的窗口下切换,并可以自由的重定向各个窗口的输入和输出。Screen实现了基本的文本操作,如复制粘贴等;还提供了类似滚动条的功能,可以查看窗口状况的历史记录。窗口还可以被分区和命名,还可以监视后台窗口的活动。

  • 会话共享

Screen可以让一个或多个用户从不同终端多次登录一个会话,并共享会话的所有特性(比如可以看到完全相同的输出)。它同时提供了窗口访问权限的机制,可以对窗口进行密码保护。

GNU’s Screen 官方站点:http://www.gnu.org/software/screen/

三、语法

# screen [-AmRvx -ls -wipe][-d <作业名称>][-h <行数>][-r <作业名称>][-s ][-S <作业名称>]

参数说明

-A 将所有的视窗都调整为目前终端机的大小。 
-d <作业名称> 将指定的screen作业离线。 
-h <行数> 指定视窗的缓冲区行数。 
-m 即使目前已在作业中的screen作业,仍强制建立新的screen作业。 
-r <作业名称> 恢复离线的screen作业。 
-R 先试图恢复离线的作业。若找不到离线的作业,即建立新的screen作业。 
-s 指定建立新视窗时,所要执行的shell。 
-S <作业名称> 指定screen作业的名称。 
-v 显示版本信息。 
-x 恢复之前离线的screen作业。 
-ls或–list 显示目前所有的screen作业。 
-wipe 检查目前所有的screen作业,并删除已经无法使用的screen作业。

四、常用screen参数

screen -S yourname -> 新建一个叫yourname的session 
screen -ls -> 列出当前所有的session 
screen -r yourname -> 回到yourname这个session 
screen -d yourname -> 远程detach某个session 
screen -d -r yourname -> 结束当前session并回到yourname这个session

在每个screen session 下,所有命令都以 ctrl+a(C-a) 开始。 
C-a ? -> 显示所有键绑定信息 
C-a c -> 创建一个新的运行shell的窗口并切换到该窗口 
C-a n -> Next,切换到下一个 window  
C-a p -> Previous,切换到前一个 window  
C-a 0..9 -> 切换到第 0..9 个 window 
Ctrl+a [Space] -> 由视窗0循序切换到视窗9 
C-a C-a -> 在两个最近使用的 window 间切换  
C-a x -> 锁住当前的 window,需用用户密码解锁 
C-a d -> detach,暂时离开当前session,将目前的 screen session (可能含有多个 windows) 丢到后台执行,并会回到还没进 screen 时的状态,此时在 screen session 里,每个 window 内运行的 process (无论是前台/后台)都在继续执行,即使 logout 也不影响。  
C-a z -> 把当前session放到后台执行,用 shell 的 fg 命令则可回去。 
C-a w -> 显示所有窗口列表 
C-a t -> Time,显示当前时间,和系统的 load  
C-a k -> kill window,强行关闭当前的 window 
C-a [ -> 进入 copy mode,在 copy mode 下可以回滚、搜索、复制就像用使用 vi 一样 
    C-b Backward,PageUp  
    C-f Forward,PageDown  
    H(大写) High,将光标移至左上角  
    L Low,将光标移至左下角  
    0 移到行首  
    $ 行末  
    w forward one word,以字为单位往前移  
    b backward one word,以字为单位往后移  
    Space 第一次按为标记区起点,第二次按为终点  
    Esc 结束 copy mode  
C-a ] -> Paste,把刚刚在 copy mode 选定的内容贴上

五、使用 screen

5.1 安装screen

流行的Linux发行版(例如Red Hat Enterprise Linux)通常会自带screen实用程序,如果没有的话,可以从GNU screen的官方网站下载。

[root@TS-DEV ~]# yum install screen

[root@TS-DEV ~]

# rpm -qa|grep screen screen-4.0.3-4.el5

[root@TS-DEV ~]

#

5.2 创建一个新的窗口

安装完成后,直接敲命令screen就可以启动它。但是这样启动的screen会话没有名字,实践上推荐为每个screen会话取一个名字,方便分辨:

[root@TS-DEV ~]# screen -S david 

screen启动后,会创建第一个窗口,也就是窗口No. 0,并在其中打开一个系统默认的shell,一般都会是bash。所以你敲入命令screen之后,会立刻又返回到命令提示符,仿佛什么也没有发生似的,其实你已经进入Screen的世界了。当然,也可以在screen命令之后加入你喜欢的参数,使之直接打开你指定的程序,例如:

[root@TS-DEV ~]# screen vi david.txt

screen创建一个执行vi david.txt的单窗口会话,退出vi 将退出该窗口/会话。

5.3 查看窗口和窗口名称

打开多个窗口后,可以使用快捷键C-a w列出当前所有窗口。如果使用文本终端,这个列表会列在屏幕左下角,如果使用X环境下的终端模拟器,这个列表会列在标题栏里。窗口列表的样子一般是这样:

0$ bash  1-$ bash  2*$ bash  

这个例子中我开启了三个窗口,其中*号表示当前位于窗口2,-号表示上一次切换窗口时位于窗口1。

Screen默认会为窗口命名为编号和窗口中运行程序名的组合,上面的例子中窗口都是默认名字。练习了上面查看窗口的方法,你可能就希望各个窗口可以有不同的名字以方便区分了。可以使用快捷键C-a A来为当前窗口重命名,按下快捷键后,Screen会允许你为当前窗口输入新的名字,回车确认。

5.4 会话分离与恢复

你可以不中断screen窗口中程序的运行而暂时断开(detach)screen会话,并在随后时间重新连接(attach)该会话,重新控制各窗口中运行的程序。例如,我们打开一个screen窗口编辑/tmp/david.txt文件:

[root@TS-DEV ~]# screen vi /tmp/david.txt

之后我们想暂时退出做点别的事情,比如出去散散步,那么在screen窗口键入C-a d,Screen会给出detached提示:

暂时中断会话

半个小时之后回来了,找到该screen会话:

[root@TS-DEV ~]# screen -ls

重新连接会话:

[root@TS-DEV ~]# screen -r 12865

一切都在。

当然,如果你在另一台机器上没有分离一个Screen会话,就无从恢复会话了。

这时可以使用下面命令强制将这个会话从它所在的终端分离,转移到新的终端上来:

5.5 清除dead 会话

如果由于某种原因其中一个会话死掉了(例如人为杀掉该会话),这时screen -list会显示该会话为dead状态。使用screen -wipe命令清除该会话:

5.6 关闭或杀死窗口

正常情况下,当你退出一个窗口中最后一个程序(通常是bash)后,这个窗口就关闭了。另一个关闭窗口的方法是使用C-a k,这个快捷键杀死当前的窗口,同时也将杀死这个窗口中正在运行的进程。

如果一个Screen会话中最后一个窗口被关闭了,那么整个Screen会话也就退出了,screen进程会被终止。

除了依次退出/杀死当前Screen会话中所有窗口这种方法之外,还可以使用快捷键C-a :,然后输入quit命令退出Screen会话。需要注意的是,这样退出会杀死所有窗口并退出其中运行的所有程序。其实C-a :这个快捷键允许用户直接输入的命令有很多,包括分屏可以输入split等,这也是实现Screen功能的一个途径,不过个人认为还是快捷键比较方便些。

六、screen 高级应用

6.1 会话共享

还有一种比较好玩的会话恢复,可以实现会话共享。假设你在和朋友在不同地点以相同用户登录一台机器,然后你创建一个screen会话,你朋友可以在他的终端上命令:

[root@TS-DEV ~]# screen -x

这个命令会将你朋友的终端Attach到你的Screen会话上,并且你的终端不会被Detach。这样你就可以和朋友共享同一个会话了,如果你们当前又处于同一个窗口,那就相当于坐在同一个显示器前面,你的操作会同步演示给你朋友,你朋友的操作也会同步演示给你。当然,如果你们切换到这个会话的不同窗口中去,那还是可以分别进行不同的操作的。

6.2 会话锁定与解锁

Screen允许使用快捷键C-a s锁定会话。锁定以后,再进行任何输入屏幕都不会再有反应了。但是要注意虽然屏幕上看不到反应,但你的输入都会被Screen中的进程接收到。快捷键C-a q可以解锁一个会话。

也可以使用C-a x锁定会话,不同的是这样锁定之后,会话会被Screen所属用户的密码保护,需要输入密码才能继续访问这个会话。

6.3 发送命令到screen会话

在Screen会话之外,可以通过screen命令操作一个Screen会话,这也为使用Screen作为脚本程序增加了便利。关于Screen在脚本中的应用超出了入门的范围,这里只看一个例子,体会一下在会话之外对Screen的操作:

[root@TS-DEV ~]# screen -S sandy -X screen ping www.baidu.com

这个命令在一个叫做sandy的screen会话中创建一个新窗口,并在其中运行ping命令。

6.4 屏幕分割

现在显示器那么大,将一个屏幕分割成不同区域显示不同的Screen窗口显然是个很酷的事情。可以使用快捷键C-a S将显示器水平分割,Screen 4.00.03版本以后,也支持垂直分屏,快捷键是C-a |。分屏以后,可以使用C-a <tab>在各个区块间切换,每一区块上都可以创建窗口并在其中运行进程。

可以用C-a X快捷键关闭当前焦点所在的屏幕区块,也可以用C-a Q关闭除当前区块之外其他的所有区块。关闭的区块中的窗口并不会关闭,还可以通过窗口切换找到它。

6.5 C/P模式和操作

screen的另一个很强大的功能就是可以在不同窗口之间进行复制粘贴了。使用快捷键C-a <Esc>或者C-a [可以进入copy/paste模式,这个模式下可以像在vi中一样移动光标,并可以使用空格键设置标记。其实在这个模式下有很多类似vi的操作,譬如使用/进行搜索,使用y快速标记一行,使用w快速标记一个单词等。关于C/P模式下的高级操作,其文档的这一部分有比较详细的说明。

一般情况下,可以移动光标到指定位置,按下空格设置一个开头标记,然后移动光标到结尾位置,按下空格设置第二个标记,同时会将两个标记之间的部分储存在copy/paste buffer中,并退出copy/paste模式。在正常模式下,可以使用快捷键C-a ]将储存在buffer中的内容粘贴到当前窗口。

6.6 更多screen功能

同大多数UNIX程序一样,GNU Screen提供了丰富强大的定制功能。你可以在Screen的默认两级配置文件/etc/screenrc和$HOME/.screenrc中指定更多,例如设定screen选项,定制绑定键,设定screen会话自启动窗口,启用多用户模式,定制用户访问权限控制等等。如果你愿意的话,也可以自己指定screen配置文件。

以多用户功能为例,screen默认是以单用户模式运行的,你需要在配置文件中指定multiuser on 来打开多用户模式,通过acl*(acladd,acldel,aclchg…)命令,你可以灵活配置其他用户访问你的screen会话。更多配置文件内容请参考screen的man页。

Unity性能优化1 2 3

堆内存优化

就目前Unity所使用的Mono版本而言,Mono堆内存分配特点是,一旦分配,就不会返还给系统,无论堆内存使用了多少,因此需要注意影响堆内存分配的因素

  1. 游戏中使用到的配置文件的大小
  2. 检测是否有较大的Container(Array,List,Dictionary)存在,比如缓存池…

资源加载

  1. 常用的资源应避免频繁加载和卸载,可以考虑将其常驻于内存
  2. 如果要使用加载AssetBundle,尽量使用 New WWW加载,而非LoadFromMemory方式,LoadFromMemory加载效率比New WWW低,除非有特殊需求

场景加载优化

简化资源
  1. 将项目中RGBA32和RGBA16的贴图转化成ETC1纹理进行加载,这样既可以减少App包体大小也可以提高加载速度
  2. 对场景中网格数据进行压缩,简化场景中的网格数据,减少不必要的数据占用,可以尝试使用AssetStore中的SimpleLOD等简化工具堆网络模型简化
  3. 根据机型采用不同的渲染LOD,降低低端设备的渲染压力

去掉Log输出

不单单是加载场景的时候需要关闭log输出在平时也应该注意删掉已经弃用的输出语句,尤其是在打包的时候一定要关掉log输出,或者只保留非常关键的输出语句

严格检查资源加载策略

尽量避免多次重复的加载卸载相同的资源,可以考虑内存常驻
注意处理依赖关系,规划AssetBundle加载方案(比如shader抽离等)

控制场景中材质资源使用数量

Shader优化

通过AssetBundle以来关系打包将Shader进行抽离,变成单独含有Shader的AssetBundle文件,这样在游戏启动时,加载AssetBundle并对Shader进行统一解析初始化,Shader占内存小,可以考虑常驻内存


UI优化

  1. 在内存允许的情况下,添加缓存机制,比如怪物,角色,或者预设,使用SetActive()方式进行,避免Instantic的高额开销
  2. UI元素的OnEnable和OnDisable都会进行比较多的操作,也会有较大的CPU开销,对于点击频率很高的界面,更高效的做法是 。 A:改变UI位置(以UIPanel为单位)实现隐藏显示,因为位置改变不会产生多余的堆内存和CPU消耗,同时也节省了Enable和Disable的CPU开销。B:通过设置摄像机的Culling Mask 来实现UI的显示隐藏,同样避免Enable/disable操作。(不过要记得将移出的panel设为static并停止所有UI元素的动画等)
  3. 添加延时机制避免大量重复性显示隐藏带来的消耗,对于打开一个界面要释放很多资源问题,可以考虑添加延迟机制,避免同一帧加载实例化的东西太多
  4. 对于动态出现和消失的UI元素可以考虑拆分到子UIPanel中,比如战斗中伤害飘字,通过拆分Panel的方法控制开销

物理系统优化

  1. Rigidbody和Collider是对物理性能影响比较大的因素,注意控制其数量
  2. 通过Layer梳理碰撞检测,避免发生大量不必要的碰撞检测
  3. 尝试开启“Optimize Mesh Data”选项,在Player Setting 的Other Setting 中,勾选后,引擎会在发布时遍历所有网格数据,将其多余的进行去除,从而降低数据量大小。需要注意的是,这里的多余是值得 Mesh数据中包含了渲染时Shader中所不需要的数据,例如,Mesh中包含Position,uv,color,normal等顶点数据,但其渲染所用的shader只需要Position,uv,那么color和normal将会被认为是 多余 的数据,引擎在发布游戏的时候会自动去除。但是。需要注意的是,对于Runtime情况下有更换Shader需求的Mesh,如果Runtime时需要为某一个Gameobject更换更复杂,需要访问更多订点属性的Shader 的话,建议次阿娘这些Shader挂载在相应的Prefab上,以免引擎去除Runtime中会进行使用的网格数据。
  4. 通过依赖关系对资源进行AssetBundle打包。不仅可以对资源热更新,同事可以降低资源在内存中的冗余度,以及将部分资源进行预加载(Shader等),尽可能避免重复加载的CPU占用

纹理格式

图集Alpha通道拆分(后面有机会在说)
项目中的RGBA32,ARGB32和RGBA16格式的纹理资源进行进一步检测,尽可能将其转换为两个ETC1纹理(RGB ETC1纹理 + Alpha ETC1 纹理)
注意纹理冗余
造成纹理冗余的原因一般有三种情况
1.资源重名
2.AssetBundle文件创建时将同种资源打包到不同的AssetBundle文件中
3.资源加载后未完全卸载


CPU优化

渲染模块

降低Draw Call

  • 降低Draw Call的方法则主要是减少所渲染物体的材质种类,并通过Draw Call Batching来减少其数量
  • 通过把纹理打包成图集来尽量减少材质的使用。
  • 尽量少的使用反光啦,阴影啦之类的,因为那会使物体多次渲染。

但是,需要注意的是,游戏性能并非Draw Call越小越好。这是因为,决定渲染模块性能的除了Draw Call之外,还有用于传输渲染数据的总线带宽。当我们使用Draw Call Batching将同种材质的网格模型拼合在一起时,可能会造成同一时间需要传输的数据(Texture、VB/IB等)大大增加,以至于造成带宽“堵塞”,在资源无法及时传输过去的情况下,GPU只能等待,从而反倒降低了游戏的运行帧率。

简化资源

  • 简化网格资源、不合规的纹理资源等,尽量不做作多余的渲染开销
  • LOD、Occlusion Culling和Culling Distance等等

UI模块
在NGUI的优化方面,UIPanel.LateUpdate为性能优化的重中之重,它是NGUI中CPU开销最大的函数
对于UIPanel.LateUpdate的优化,主要着眼于UIPanel的布局,其原则如下:

1. 尽可能将动态UI元素和静态UI元素分离到不同的UIPanel中(UI的重建以UIPanel为单位),从而尽可能将因为变动的UI元素引起的重构控制在较小的范围内; 2.尽可能让动态UI元素按照同步性进行划分,即运动频率不同的UI元素尽可能分离放在不同的UIPanel中; 3.控制同一个UIPanel中动态UI元素的数量,数量越多,所创建的Mesh越大,从而使得重构的开销显著增加。比如,战斗过程中的HUD运动血条可能会出现较多,此时,建议研发团队将运动血条分离成不同的UIPanel,每组UIPanel下5~10个动态UI为宜。这种做法,其本质是从概率上尽可能降低单帧中UIPanel的重建开销。

GC

1.字符串连接的处理。因为将两个字符串连接的过程,其实是生成一个新的字符串的过程。而之前的旧的字符串自然而然就成为了垃圾。而作为引用类型的字符串,其空间是在堆上分配的,被弃置的旧的字符串的空间会被GC当做垃圾回收。 2.尽量不要使用foreach,而是使用for。foreach其实会涉及到迭代器的使用,而据传说每一次循环所产生的迭代器会带来24 Bytes的垃圾。那么循环10次就是240Bytes。 3.不要直接访问gameobject的tag属性。比如if (go.tag == “human”)最好换成if (go.CompareTag (“human”))。因为访问物体的tag属性会在堆上额外的分配空间。如果在循环中这么处理,留下的垃圾就可想而知了。 4.使用“池”,以实现空间的重复利用。 5.最好不用LINQ的命令,因为它们会分配临时的空间,同样也是GC收集的目标。而且我很讨厌LINQ的一点就是它有可能在某些情况下无法很好的进行AOT编译。比如“OrderBy”会生成内部的泛型类“OrderedEnumerable”。这在AOT编译时是无法进行的,因为它只是在OrderBy的方法中才使用。所以如果你使用了OrderBy,那么在IOS平台上也许会报错。

代码效率

1.不要频繁使用GetComponent,尤其是在循环中 2.使用内建的数组,比如用Vector3.zero而不是new Vector(0, 0, 0); 3.对于方法的参数的优化:善于使用ref关键字。值类型的参数,是通过将实参的值复制到形参,来实现按值传递到方法,也就是我们通常说的按值传递。复制嘛,总会让人感觉很笨重。比如Matrix4x4这样比较复杂的值类型,如果直接复制一份新的,反而不如将值类型的引用传递给方法作为参数。 4.使用“池”不只是UI上的组建场景中的动态资源也可以使用,减少Instantiate次数,还有就是更改位置要比隐藏显示要好

GPU优化

减少顶点数量,简化计算复杂度。

1.保持材质的数目尽可能少。这使得Unity更容易进行批处理。
2.使用纹理图集(一张大贴图里包含了很多子贴图)来代替一系列单独的小贴图。它们可以更快地被加载,具有很少的状态转换,而且批处理更友好。
3.如果使用了纹理图集和共享材质,使用Renderer.sharedMaterial 来代替Renderer.material 。
4.使用光照纹理(lightmap)而非实时灯光。
5.使用LOD,好处就是对那些离得远,看不清的物体的细节可以忽略。
6.遮挡剔除(Occlusion culling)
7.使用mobile版的shader。因为简单。

压缩图片

1.使用适当的图片格式
2.使用mipmap

CentOS7 安装Git

1、查看当前git版本:
git –version

查看最新版git:
访问https://www.kernel.org/pub/software/scm/git/
或者https://github.com/git/git/releases
2、官网下载:wget https://Github.com/Git/Git/archive/v2.11.0.tar.gz(建议本机迅雷下载rz到服务器,安装yum install lrzsz后rz即可)
解压:
tar -zxvf git-2.11.0.tar.gz
3、cd git-2.11.0
4、为了防止git安装完后出现git clone时候提示fatal: Unable to find remote helper for ‘https’提前先安装libcurl-develyum install libcurl-devel
5、移除旧版本
git:yum remove git
6、make configure
如果报错/bin/sh: autoconf: command not found:安装libtool即可:yum install  autoconf automake libtool
正常会打印:GEN configure执行
7、./configure –prefix=/usr/local/git –with-iconv =/usr/local/lib(建议优先尝试后者)
或者./configure –prefix=/usr/local/git –with-iconv –with-curl –with-expat=/usr/local/lib(如果没有安装libiconv请自行安装)
make && make install
①如果报错:cache.h:40:18: fatal error: zlib.h: No such file or directory安装zlib:yum install zlib、yum install zlib-devel
②如果报错:make[1]: *** [perl.mak] Error 2
make: *** [perl/perl.mak] Error 2安装:yum install perl-ExtUtils-MakeMaker package

3:报错:make[1]: Leaving directory `/home/app/git-2.5.5/git-gui’  还不知道怎么解决。 
8、echo “export PATH=$PATH:/usr/local/git/bin” >> /etc/bashrc
9、source /etc/bashrc
10、git –version 编译git时报错: zlib.h: No such file or directory    缺少 zlib的头文件, 开发包没装,    yum install zlib (系统默认已经装上)    
yum install zlib-devel  
原文地址:https://www.cnblogs.com/BinBinStory/p/7113956.html

MongoDB C# Driver 快速入门指南

这是MongoDB driver的第一部分。在这一部分,你可以看到如何去执行一些数据库的基本CRUD(C-创建,R-读取,U-更新,D-删除)操作。

连接

以下展示了三种连接到MongoDB远程服务器和本地服务器的方式 :

// 连接到单实例MongoDB服务
// 这种连接方式不会自动检测连接的节点是主节点还是复制集的成员节点
var client = new MongoClient();

// 或者使用string连接本地服务器,localhost=127.0.0.1,连接到单实例
var client = new MongoClient("mongodb://localhost:27017");

// 连接到复制集(多节点)
var client = new MongoClient("mongodb://localhost:27017,localhost:27018,localhost:27019");

客户端实例现在可以拥有连接到连接字符串中指定的服务器或服务器的连接池。

MongoClient

MongoClient 实例实际上表示一个连接数据库的连接池;

你仅仅只需要一个MongoClient 类实例,即使在多线程情况下;

标注:
实际上,你只需要为给定的集群创建一个MongoClient实例,并在应用程序中使用它。但是,如果连接字符串是相同的,那么创建多个MongoClient将仍然共享相同的连接池。

Get a Database

获取一个数据库实例,列举数据库的名称可以通过client中的GetDatabase方法,在数据库存在的情况下,该方式都是可行的。它将在首次被调用时创建。

var database = client.GetDatabase("foo");

现在,database变量保存了对数据库“foo”的引用.

Get a Collection

获取一个集合实例,列举集合的名称可以通过database中GetCollection<TDocument>.在集合存在的情况下,它将在首次被调用时创建。

var collection = database.GetCollection<BsonDocument>("bar");

现在,collection变量保存了对数据库“foo”下“bar”集合的引用.

标注:
泛型参数TDocument表示集合中存在的模式,使用一个BsonDocument来表示没有预定的模式。

Insert a Document

一旦你拥有了collection实例,你就可以插入一个文档到集合中。例如,考虑下面的JSON文档,它是一个包含了一个字段信息的嵌入式文档。

{
     "name": "MongoDB",
     "type": "database",
     "count": 1,
     "info": {
         x: 203,
         y: 102
     }
}

你可以使用.NET driver中的BsonDocument类创建这个文档,方式如下:

var document = new BsonDocument
{
    { "name", "MongoDB" },
    { "type", "Database" },
    { "count", 1 },
    { "info", new BsonDocument
        {
            { "x", 203 },
            { "y", 102 }
        }
    }
};

把这个文档插入到集合中,可以是使用InsertOne或者InsertOneAsync方法

collection.InsertOne(document);//同步
await collection.InsertOneAsycn(document);//异步

标注:
.NET driver 当前已全部支持异步操作。关于更多的async和await的信息,参见MSDN documentation
https://msdn.microsoft.com/en-us/library/hh191443.aspx
驱动中所有的API都已经同时支持同步和异步.

Insert Multiple Documents

插入多条数据到数据库,可以使用InsertMany或者InsertManyAsync两种方式.

// 生成 100 个counter从0~99递增的文档
var documents = Enumerable.Range(0, 100).Select(i => new BsonDocument("counter", i));

插入数据

collection.InsertMany(documnets);
await collection.InsertManyAsycn(documents);

Counting Documents

现在,我们插入了101个文档到数据库里面(100在循环中,首次插入1),我们可以核查这些数据,如果我们使用Count或者CountAsycn方法. 下面的代码应该可以使得count的值为101.

var count = collection.Count(new BsonDocument());
or
var count = await collection.CountAsync(new BsonDocument());

标注:
空的BsonDocument参数是一个过滤器。在这里,指的是要计算所有的文档.

Query the Collection

使用Find方法去集合中查询. 该方法会返回一个IFindFluent<TDocument, TProjection>实例,它提供一个接口链接find操作设置.

Find the First Document in a Collection

调用FirstOrDefault 或者FirstOrDefaultAsync 方法,可以获取集合的第一个文档.FirstOrDefault返回第一个文档或者null. 当你只需要一个匹配的文档或只对第一个文档感兴趣时,该方法非常有用.

下面的例子将会打印出再集合中查询出来的第一个文档:

var document = collection.Find(new BsonDocument()).FirstOrDefault();
Consloe.WriteLine(document.ToString());
var document = await collection.Find(new BsonDocument()).FirstOrDefaultAsync();
Console.WriteLine(document.ToString());

该例子将会打印出以下内容:

{ 
    "_id": ObjectId("5940f2b98198abd6a5eea7b1") },
    "name": "MongoDB", 
    "type": "database", 
    "count": 1,
    "info": { "x" : 203, "y" : 102 } 
}

元素 “id” 为 MongoDB 数据库自动添加到文档中,这是打印出来的内容与插入的内容不一致的原因。MongoDB数据库内部保留所有以 “_” 和 “$” 开头的字段名称.

Find All Documents in a Collection

使用ToList或者ToListAsycn方法可以检索到集合中的所有文档,当需要返回的文档比较少量时,该方法非常有用.

var documents = collection.Find(new BsonDocument()).ToList();
var documents = await collection.Find(new BsonDocument()).ToListAsync();

如果返回的文档数量比预期的大,可以使用通过迭代的方式进行处理。ForEachAsync将会为每个返回的文档调用一个回调。

await collection.Find(new BsonDocument()).ForEachAsync(d => Console.WriteLined(d));

如果使用的是同步的API,则要使用C#中的ToEnumerable抽象方法去迭代每个文档:

var cursor = collection.Find(new BsonDocument()).ToCursor();
foreach (var document in cursor.ToEnumerable())
{
    Console.WriteLine(document);   
}

上面的例子将会打印出相同的信息。更多的信息参见reference documention

Get a Single Document With a Filter

在一个集合中,我们可以创建一个筛选器传递给Find方法去获取一个文档的子集。例如,如果我们想查找“i”字段的值为71的文档,我们可以使用如下的方式:

var filter = Builders<BsonDocument>.Filter.Eq("i", 71);
var document = collection.Find(filter).First();
Console.WriteLine(document);
var document = await collection.Find(filter).FirstAsync();
Console.WriteLine(document);

以上应该仅打印出一个文档:

{ "_id" : ObjectId("5515836e58c7b4fbc756320b"), "i" : 71 }

标注:
使用 Filter,Sort 和 Projection 以简单和简洁的方式创建一个查询.

Get a Set of Documents With a Filter

我们也可以从集合中获取一组文档。例如,如果我们获取所有符合 i > 50 条件的文档,可以使用如下的方式:

var filter = Builders<BsonDocument>.Filter.Gt("i", 50);// Gt表示大于
var cursor = collection.Find(filter).ToCursor();
foreach (var document in cursor.ToEnumerable())
{
    Console.WriteLine(document);   
}
await collection.Find(filter).ForEachAsync(document => Console.WriteLine(document));

还可以限定一个范围查询,例如 50 < i <= 100;

var filterBuilder = Builders<BsonDocument>.Filter;
var filter = filterBuilder.Gt("i", 50) & filterBuilder.Lte("i", 100);//Lt表示小于,Lte表示小于等于
var cursor = collection.Find(filter).ToCursor();
foreach (var document in cursor.ToEnumerable())
{
    Console.WriteLine(document);   
}
await collection.Find(filter).ForEachAsync(document => Console.WriteLine(document));

Sorting Documents

我们可以通过调用 Sort 方法来创建一个排序匹配查询。在现有的 filter 构造方法下,我们可以使用 Descending 建立一个降序构造器来排序我们的文档:

var filter = Builders<BsonDocument>.Filter.Exists("i");
var sort = Builders<BsonDocument>.Sort.Descending("i");
var document = collection.Find(filter).Sort(sort).First();
var document = await collection.Find(filter).Sort(sort).FirstAsync();

Projecting Fields(映射字段)

很多时候,我们不需要文档中包含的所有字段,Projection 构造器可以在一个查询操作中构造映射字段。下面的例子中,我们排除了“_id”字段,并且输出第一个匹配的文档:

var projection = Builders<BsonDocument>.Projection.Exclude("_id");
var document = collection.Find(new BsonDocument()).Project(projection).First();
Console.WriteLine(document.ToString());
var document = await collection.Find(new BsonDocument()).Project(projection).FirstAsync();
Console.WriteLine(document.ToString());

Updating Documents

MongoDB 支持多种更新操作方式

更新最多一个文档(如果没有匹配筛选器,可能为零个文档),使用UpdateOne或者UpdateOneAsync去指定筛选器并更新匹配的文档。下面,我们更新筛选器为 i == 10 匹配的第一个文档,并将该文档 i 的值更新为110:

var filter = Builders<BsonDocument>.Filter.Eq("i", 10);
var update = Builders<BsonDocument>.Update.Set("i", 110);
collection.UpdateOne(filter, update);
await collection.UpdateOneAsync(filter, update);

更新筛选器匹配的所有文档,使用UpdateMany或者UpdateManyAsync方法。下面例子,将把所有 i < 100 匹配的文档中 i 的值增加 100。

var filter = Builders<BsonDocument>.Filter.Lt("i", 100);
var update = Builders<BsonDocument>.Update.Inc("i", 100);// Inc操作符表示:给i字段增加某个大小的值

var result = collection.UpdateOne(filter, update);

if (result.IsModifiedCountAvailable)
{
    Console.WriteLine(result.ModifiedCount);
}

var result = await collection.UpdateOneAsync(filter, update);

if (result.IsModifiedCountAvailable)
{
    Console.WriteLine(result.ModifiedCount);
}

更新方法返回的结果为UpdateResult,它提供关于该操作的信息,包括更新后修改的文档的数量。

标注:
根据MongoDB数据库的版本,某些特性可能无法使用。在这些情况下,我们已经尝试了检查是否有能力检查它们的可用性。

Deleting Documents

删除最多一个文档(如果没有匹配筛选器,可能为零个文档),使用 DeleteOne 或者DeleteOneAsync方法:

var filter = Builders<BsonDocument>.Filter.Eq("i", 110));
collection.DeleteOne(filter);
await collection.DeleteOneAsync(filter);

删除筛选器匹配的所有文档,使用DeleteMany 或者 DeleteManyAsync 方法。下面是删除所有 i >= 100 匹配的文档:

var filter = Builders<BsonDocument>.Filter.Gte("i", 100));// Gte表示大于等于

var result = collection.DeleteMany(filter);

Console.WriteLine(result.DeletedCount);

var result = await collection.DeleteManyAsync(filter);

Console.WriteLine(result.DeletedCount);

删除方法返回的结果为DeleteResult ,它提供关于该操作的信息,包括删除的文档数量。

Bulk Writes (批量操作)

Bulk 操作有两种类型:

有序Bulk操作
以有序的方式执行所有的操作,并且在首次遇到异常时抛出异常。

无序Bulk操作
执行所有的操作,并记录操作过程中的全部异常。无序的批量操作不能保证执行的顺序。
让我们看一看下面的两个关于有序和无序的操作例子:

var models = new WriteModel<BsonDocument>[] 
{
    new InsertOneModel<BsonDocument>(new BsonDocument("_id", 4)),
    new InsertOneModel<BsonDocument>(new BsonDocument("_id", 5)),
    new InsertOneModel<BsonDocument>(new BsonDocument("_id", 6)),
    new UpdateOneModel<BsonDocument>(
        new BsonDocument("_id", 1), 
        new BsonDocument("$set", new BsonDocument("x", 2))),
    new DeleteOneModel<BsonDocument>(new BsonDocument("_id", 3)),
    new ReplaceOneModel<BsonDocument>(
        new BsonDocument("_id", 3), 
        new BsonDocument("_id", 3).Add("x", 4))
};

// 1. 有序的批量操作 - 保证操作的顺序
collection.BulkWrite(models);

// 2. 无序的批量操作 - 无法保证操作的顺序
collection.BulkWrite(models, new BulkWriteOptions { IsOrdered = false });

异步

// 1. 有序的批量操作 - 保证操作的顺序
await collection.BulkWriteAsync(models);

// 2. 无序的批量操作 - 无法保证操作的顺序
await collection.BulkWriteAsync(models, new BulkWriteOptions { IsOrdered = false });

重要:
批量操作功能在MongoDB数据库版本为2.6及之前的版本不被推荐使用,在性能上有较大的影响。