有2个嵌套的数组:

如果我想查询comments里score大于5的记录:
testProvider.find({"comments.score":{"$gt":5}},{},function(err, result){
     console.log(result);
});

返回了查找到的记录,说明了查找有效果了:


这样查找返回的数据都是把匹配的整个文档返回过来了。
 
如果我觉得其中有个字段是没必要返回给我的可以设置这个字段为0:
testProvider.find({"comments.score":{"$gt":5}},{'comments.others':0},function(err, result) {
    console.log(JSON.stringify(result));
});
可以看到返回的结果中已经没有others这个字段了

如果我想查询comments数组里面的某个子文档中others数组里面name为a的记录:
testProvider.find({"comments.others.name":'a'},{},function(err, result) {
    console.log(JSON.stringify(result));
});
返回的结果中的一部分如下图:
 
从上面的几个示例中可以看到我想要查找某个符合条件的子文档时可以直接一直用'.'号表示下去而不用管其中是否有数组,如:{"comments.others.name":'a'}
一些高级的查询语法看这一篇:http://blog.sina.com.cn/s/blog_abba9c1d0101eti7.html
 

1、使用"$size"可以查询指定长度的数组

查询数组长度为3的数组db.users.find({"emails":{"$size":3}})

常见的查询是数组长度范围的查询."$size"并不能与其他查询子句组合(如:"$gt"),但是这种查询可以通过

在文档中添加一个"size"键的方式来实现.这样每一次向指定数组添加元素的时候,同时增加"size"值.原来这样

的更新:  db.users.update({"$push":{"emails":"295240648@139.com"}})

变成这样的更新:  db.users.update({"$push":{"emails":"295240648@139.com"},"$inc":{"size":1}})

这样就可以这样查询了 db.users.find({"size":{"$gt":3}})

2、使用"$slice"查询

find的第二个参数是可选的,可以指定返回那些键,"$slice"返回数组的一个子集合

返回emails数组的前两个元素   db.users.find({"userName":"refactor"},{"emails":{"$slice":2}})

返回emails数组的后两个元素   db.users.find({"userName":"refactor"},{"emails":{"$slice":-2}})

返回emails数组的第2个和第11个元素.如果数组不够11个,则返回第2个后面的所有元素

db.users.find({"userName":"refactor"},{"emails":{"$slice":[1,10]}})

"$slice"默认将返回文档中的所有键.

3、要正确指定一组条件,而不用指定每个键,要使用"$elemMatch".这种模糊的命名条件能用来部分指定匹配数组中

的单个内嵌文档的限定条件.正确写法应该是:

db.blog.find(
  {
    "comments":
    {
      "$elemMatch":
      {
        "author":"refactor",
        "score":{"$gte":5}
      }
    }
  }
)

"$elemMatch"将限定条件进行分组,仅当需要对一个内嵌文档的多个键操作时才会用到.

4."$where"查询

"$where"可以执行任意javascript作为查询的一部分.这使得查询能做(几乎)任何事情.

最典型的应用就是比较文档中的两个键的值是否相等.

如:db.blog.insert({"title":"refactor","content":"refactor"})

db.blog.insert({"title":"refactor1","content":"refactor content"})

第一个文档title键和content键的值相同.要返回该文档.

db.blog.find(
  {
    "$where":function()
          {
            for(var current in this)
            {
              for(var other in this)
              {
                if(current!=other&&this[current]==this[other])
                {
                  return true;
                }
              }
            }
            return false;
          }
  }
)
如果函数返回true,文档就作为结果的一部分被返回.

上面是用一个函数,也可以用一个字符串指定"$where"查询.下面两种方式是等价的:

db.blog.find({"$where":"this.x+this.y==10"})
db.blog.find({"$where":"function(){return this.x+this.y==10;}"})

不是非常必要时,应避免"$where"查询.它在速度上要比常规查询慢的多.每个文档都要从BSON转换成

javascript对象,然后通过"$where"的表达式来运行.它还不能利用索引.

将常规查询作为前置过滤,与"$where"组合使用才能不牺牲性能,如果有可能的话,用索引根据非"$where"

子句进行过滤,"$where"只用于对结果进行调优

上面的4个查询转自:http://www.cnblogs.com/refactor/archive/2012/07/30/2591344.html

http://www.cnblogs.com/refactor/archive/2012/07/31/2591544.html

更新子文档:
在更新子文档时和查询时又有所不同(遇到数组时多加一个$符号):
testProvider.update({"comments.score":4},{'$set':{'comments.$.score':1}},{multi:true,w:1},function(err, numberUpdated) {
    console.log("numberUpdated: ", numberUpdated);
});
查询下可以发现结果已经改变了:

如果我想往一个子文档的数组中插入一个子文档时可以使用push:
testProvider.update({"comments.score":1},{'$push':{'comments.$.others':{"name":"j","age":"24"}}},{multi:true,w: 1},function(err, numberUpdated) {
    console.log("numberUpdated: ", numberUpdated);
});
查询之后可以发现comments.others里多了一个子文档,表明已经插入进去了:

如果我想把刚刚插入的子文档删除时,可以使用pull:
testProvider.update({"comments.score":1},{'$pull':{'comments.$.others':{"name":"j"}}},{multi:true,w: 1},function(err, numberUpdated) {
    console.log("numberUpdated: ", numberUpdated);
});
查询之后可以发现结果已经改变:
注意:如下图所示pull值中的key对应的值必须为json格式的:

    我在使用的过程中还发现在遇到数组时使用'.$'符号时每个里面只能用一次;如上图的错误写法中就含有2个'.$'符号。所以如果子文档里嵌套有2个乃至更多数组时,很难准确的对嵌套的数组中的某一个元素进行更新。
找了一晚上,终于找到个合适的方法,都准备睡觉了,结构试了这个方法,确实可以,帮了我一个大忙啊

mongo二维数组操作的更多相关文章

  1. python的二维数组操作

    需要在程序中使用二维数组,网上找到一种这样的用法: ? 1 2 3 4 5 6 #创建一个宽度为3,高度为4的数组 #[[0,0,0], # [0,0,0], # [0,0,0], # [0,0,0] ...

  2. 06-01 Java 二维数组格式、二维数组内存图解、二维数组操作

    二维数组格式1 /* 二维数组:就是元素为一维数组的一个数组. 格式1: 数据类型[][] 数组名 = new 数据类型[m][n]; m:表示这个二维数组有多少个一维数组. n:表示每一个一维数组的 ...

  3. 整理:python的二维数组操作

    Python中初始化一个5 x 3每项为0的数组,最好方法是: multilist = [[0 for col in range(5)] for row in range(3)] 如果初始化一个二维数 ...

  4. python的二维数组操作--坑

    用到python list的二维数组,发现有一些需要注意的地方. 第一种赋值方法: list0 = [[0]*3]*4 list0[0][1] = 1 print(list0) 输出结果为: [[0, ...

  5. 在python中定义二维数组

    发表于 http://liamchzh.0fees.net/?p=234&i=1 一次偶然的机会,发现python中list非常有意思. 先看一段代码 [py]array = [0, 0, 0 ...

  6. php对二维数组进行相关操作(排序、转换、去空白等)

    php对二维数组进行相关操作(排序.转换.去空白等) 投稿:lijiao 字体:[增加 减小] 类型:转载 时间:2015-11-04   这篇文章主要介绍了php对二维数组进行相关操作,包括php对 ...

  7. C++使用VARIANT实现二维数组的操作

    C++使用VARIANT实现二维数组的操作 VARIANT变量是COM组件之间互相通信的重要的参数变量之一,它可以容纳多种不同的类型,如short.long.double等,包括各类指针和数组.组件之 ...

  8. [java学习笔记]java语言基础概述之数组的定义&常见操作(遍历、排序、查找)&二维数组

    1.数组基础 1.什么是数组:           同一类型数据的集合,就是一个容器. 2.数组的好处:           可以自动为数组中的元素从零开始编号,方便操作这些数据. 3.格式:  (一 ...

  9. 对二维数组使用指针进行操作的探索(C语言)

    /* Name: 对二维数组使用指针进行操作的探索 Copyright: Author: lingr7 Date: 01/12/18 11:55 Description: */ #include< ...

随机推荐

  1. PHP 下载文件时自动添加bom头的方法

    首先弄清楚,什么是bom头?在Windows下用记事本之类的程序将文本文件保存为UTF-8格式时,记事本会在文件头前面加上几个不可见的字符(EF BB BF),就是所谓的BOM(Byte order ...

  2. mysql报错Table '.\erchina_news\v9_search' is marked as crashed and should be repaired

    直切正题 报该问题的是表引导坏了,需要修复表就行 方法一: 找到mysql的安装目录的bin/myisamchk工具,在命令行中输入: myisamchk -c -r ../data/erchina_ ...

  3. .NET软件汉化小实例

    Author:KillerLegend Date:2014.6.18 From:http://www.cnblogs.com/killerlegend/p/3795577.html 好的,今天我们来汉 ...

  4. psd图片到html

    正确的做法是:拿到psd后,先不要做别的,直接在文本编辑器中将网页的框架写出来,不要假设这块将来css要去怎么渲染,完全自然化的标签,不加任何的css.写完之后在各个浏览器运行之后确保大体定位都没有问 ...

  5. 使用WIF实现单点登录Part I——Windows Identity Foundation介绍及环境搭建

    首先先说一下什么是WIF(Windows Identity Foundation).由于各种历史原因,身份验证和标识的管理一般都比较无规律可循.在软件里加入“身份验证”功能意味着要在你的代码里混进处理 ...

  6. 第三章 管理程序流(In .net4.5) 之 实现程序流

    1. 概述 本章内容包括 布尔表达式.流控制方式.集合遍历 以及 流跳转. 2. 主要内容 *由于该章内容比较基础,日常用的也很多,故对一些常用的基础内容不再赘述. 2.1 使用布尔表达式 熟悉下列比 ...

  7. Oracle用户,权限,角色以及登录管理 scoot 授权

    Oracle用户,权限,角色以及登录管理 1. sys和system用户的区别 system用户只能用normal身份登陆em.除非你对它授予了sysdba的系统权限或者syspoer系统权限. sy ...

  8. 转载:监控每个节点(Indices部分)

    集群的健康只是一个方面,它是对整个集群所有方面的一个很高的概括.节点状态的api是另外一个方面,它提供了关于你的集群中每个节点令你眼花缭乱的统计数据. 节点的状态提供了那么多的统计数据,在你很熟悉它们 ...

  9. JS跨域方法及原理

        JS跨域分析判断 JS跨域:在不同域之间,JS进行数据传输或通信.比如ajax向不同的域请求数据.JS获取iframe中的页面中的值(iframe内外不同域) 只要协议.端口.域名有一个不同则 ...

  10. Android开发随笔之ScrollView嵌套GridView[ 转]

    今天在开发中用到了需要ScrollView嵌套GridView的情况,由于这两款控件都自带滚动条,当他们碰到一起的时候便会出问题,即GridView会显示不全,为了解决这个问题查了N多资料,某个谷歌的 ...