最近想做一个前端控制接口字段返回的一个基础方法,通过mongodb 的find($query,$field)查询来规定查询的字段,但是遇到这么一个问题:

工作代码中有两个封装方法 :

  1. /**
    * 查询一条记录
    * @param string 集合名
    * @param array 查询条件
    * @param array 需要返回的字段
    * @return array 查询的结果
    */
    public function find_one($coll_name, $condition = array(), $ret_fields = array('_id' => 0)) {
    return $this->docsdb->find_one($coll_name, $condition, $ret_fields);
    }
  1. /**
    * 查询
    * @param string 集合名
    * @param array 查询的条件array<br/>如<i>array(col_a=>111)</i>
    * @param array 集合过滤器array<br/>完整的样子想这个:<i>array(sort=>array(col_a=>1,col_b=>-1), skip=>100, limit=>10, timeout=>5000, immortal=>true)</i>,这表示:
    * <ol>
    * <li>wrapped 以wrapped为封装为数组的键,默认按数组先后顺序</li>
    * <li>_id,默认不返回数据带有MongoID字段,如果指定了返回列的话也是一样的效果</li>
    * <li>sort 以col_a为ASC,col_b为DESC排序,可以多列组合</li>
    * <li>skip 表示从101条记录开始取数据,即跳过了前100条</li>
    * <li>limit 本次选取的条数</li>
    * <li>timeout 表示等待响应的时间(暂不使用)</li>
    * <li>immortal 表示是否维持链接永久有效,默认true,此时timeout失效(暂不使用)</li>
    * </ol>
    * @param array 需要返回的字段(通常只返回必要的字段可以加快响应速度)
    * @return mixed 查询的结果
    */
    public function find($coll_name, $condition = array(), $result_filter = array('wrapped' => '', 'with_objectId' => 0, 'timeout' => 5000, 'immortal' => true), $ret_fields = array()) {
    return $this->docsdb->find($coll_name, $condition, $result_filter, $ret_fields);
    }
  2.  
  3. **
  1. 'with_objectId' => 0 已在传入参数时设置为1
  1. **
    根据以上描述,$ret_fields就是mongodb find($query,$field)中的那个field,但是通过测试,我发现了这么一个问题,如果我想要去显示id,传入参数数组
  1. $ret_fields = array(
      '_id' => 1, 
    'account'=> 1,
    'card' => 1
    ),
    并调用find方法,根据理论来说,这个时候'_id'这个字段也是显示的,并且我通过这个条件直接查询mongodb,也是显示的,但是打印出来的数据却是不带id的,数据如下:

{
"account": "qwe",
"card": ""
}

  1. ***补充个测试结果,如果find方法不传入$ret_fields变量过去,即不限制返回字段的话,是存在'_id'
  1. 通过修改条件,发现这个'_id' => 1 这个条件写不写都没用,于是我用相同的
  1. $ret_fields去调用了find_one方法,这个时候竟然是返回'_id'字段的,数据如下

{
"_id": {
"$id": "58f472672430e11817000152"
},
"account": "qwe",
"card": ""
}

这个问题先记录在这吧,以后解决了再记录一下解决方法,如果有大神可以解释下这个原因,请不吝赐教,谢谢!

后续:通过查找底层的代码发现了如下封装:

  1. /**
    * 查询MongoDB
    * @param string 集合名
    * @param array 查询的条件array<br/>如<i>array(col_a=>111)</i>
    * @param array 集合过滤器array<br/>完整的样子想这个:<i>array(sort=>array(col_a=>1,col_b=>-1), skip=>100, limit=>10, timeout=>5000, immortal=>true)</i>,这表示:
    * <ol>
    * <li>wrapped 以wrapped为封装为数组的键,默认按数组先后顺序</li>
    * <li>_id,默认不返回数据带有MongoID字段,如果指定了返回列的话也是一样的效果</li>
    * <li>sort 以col_a为ASC,col_b为DESC排序,可以多列组合</li>
    * <li>skip 表示从101条记录开始取数据,即跳过了前100条</li>
    * <li>limit 本次选取的条数</li>
    * <li>timeout 表示等待响应的时间(暂不使用)</li>
    * <li>immortal 表示是否维持链接永久有效,默认true,此时timeout失效(暂不使用)</li>
    * </ol>
    * @param array 需要返回的字段(通常只返回必要的字段可以加快响应速度)
    * @return mixed 查询的结果
    */
    public function find($coll_name, $condition = array(), $result_filter = array('wrapped' => '', 'with_objectId' => 0, 'timeout' => 5000, 'immortal' => true), $ret_fields = array()) {
    $db_name = $this->db_name;
    $cursor = $this->mongo->$db_name->$coll_name->find($condition, $ret_fields);
    if (!empty($result_filter['skip'])) {
    $cursor->skip($result_filter['skip']);
    }
    if (!empty($result_filter['limit'])) {
    $cursor->limit($result_filter['limit']);
    }
    if (!empty($result_filter['sort'])) {
    $cursor->sort($result_filter['sort']);
    }
    if (!empty($result_filter['wrapped'])) {
    $wrapped = $result_filter['wrapped'];
    } else {
    $wrapped = '';
    }
    if (isset($result_filter['with_objectId']) && $result_filter['with_objectId'] == 1) {
    //如果指定了返回的列此项目就失效
    $with_objectId = count($ret_fields) < 1;
    } else {
    $with_objectId = 0;
    }
    if(!$with_objectId){
    if (isset($ret_fields['with_objectId']) && $ret_fields['with_objectId'] == 1) {
  2.  
  3. $with_objectId = 1;
    } else {
    $with_objectId = 0;
    }
    }
  4.  
  5. $result = array();
    $this->cursor = $cursor;
    try {
    if ($wrapped == '_id') {
    while ($ret = $cursor->getNext()) {
    $result[$ret['_id']->{'$id'}] = $ret;
    }
    } else if (strlen($wrapped)) {
    while ($ret = $cursor->getNext()) {
    $result[$ret[$wrapped]] = $ret;
    }
    } else {
    while ($ret = $cursor->getNext()) {
    $result[] = $ret;
    }
    }
    if (!$with_objectId) {
    foreach ($result as $key => $v) {
    unset($result[$key]['_id']);
    }
    }
    } catch (Exception $ex) {
    $this->errors = $ex->getMessage();
    }
    return $result;
    }
  6.  
  7. 重点在于:
  1. if(!$with_objectId){
    if (isset($ret_fields['with_objectId']) && $ret_fields['with_objectId'] == 1) {
  2.  
  3. $with_objectId = 1;
    } else {
    $with_objectId = 0;
    }
    }
    限定字段传入的参数名与mongodb不太一样,不能传_id,应该传with_objectId,这样就达到了需要的效果
  4.  
  5. ps:二次开发就是坑。

关于php查询mongodb限制返回字段的问题的更多相关文章

  1. MongoDB查询操作限制返回字段的方法

    这篇文章主要介绍了MongoDB查询操作限制返回字段的方法,需要的朋友可以参考下   映射(projection )声明用来限制所有查询匹配文档的返回字段.projection以文档的形式列举结果集中 ...

  2. PDO 查询mysql返回字段整型变为String型解决方法

    PDO 查询mysql返回字段整型变为String型解决方法 使用PDO查询mysql数据库时,执行prepare,execute后,返回的字段数据全都变为字符型. 例如id在数据库中是Int的,查询 ...

  3. PDO 查询mysql返回字段int变为String型解决方法

    PDO 查询mysql返回字段int变为String型解决方法使用PDO查询mysql数据库时,执行prepare,execute后,返回的字段数据全都变为字符型. 例如id在数据库中是Int的,查询 ...

  4. 03 - Mongodb数据查询 | Mongodb

    1.基本查询 ①方法find():查询 db.集合名称.find({条件文档}) ②方法findOne():查询,只返回第一个 db.集合名称.findOne({条件文档}) ③方法pretty(): ...

  5. hibernate框架之-查询结果集返回类型

    Hibernate支持HQL和SQL的查询,返回结果支持POJO类型或字段/数组的形式. 开发中用Hibernate进行数据库查询,用的是SQL.原来需要查询一个表的几乎所有字段,所以我使用了addE ...

  6. Java 通过JDBC查询数据库表结构(字段名称,类型,长度等)

    Java 通过JDBC查询数据库表结构(字段名称,类型,长度等) 发布者:唛唛家的豆子   时间:2012-11-20 17:54:02   Java 通过JDBC查询数据库表结构(字段名称,类型,长 ...

  7. 方法:查询MongoDB数据库中最新一条数据(JAVA)

    使用JAVA语言查询MongoDB中某个数据库某个集合的最新一条数据: MongoCollection<Document> cpu = MongoClient.getDatabase(&q ...

  8. MongoDB数据查询 --MongoDB

    1.插入测试数据 use flower db.goods.insert({'goods_name':'Hyacinth',price:10,num:800}) db.goods.insert({goo ...

  9. tp5.0 模型查询数据的返回类型,分页

    一开始用painate()这个函数的时候,发现有的查询方式不能使用这个函数,由此了解到了模型查询和普通查询返回类型的不同 1.原生查询方法 Db::query("select * from ...

随机推荐

  1. 通过pid杀死进程

    bool ****::KillProcess(DWORD pid) { // When the all operation fail this function terminate the " ...

  2. 关于itext生成pdf的新的demo(包含简单的提取txt文件的内容 和xml内容转化为pdf)

    一.用的iText版本为7.0.2版本,maven的配置如下: <dependencies> <!-- always needed --> <dependency> ...

  3. solr实现动态加载分词

    版本是5.3.0 在core(自己创建的模块)的schema.xml里面增加类型: <fieldType name="text_lj" class="solr.Te ...

  4. python------Socket网略编程+动态导入模块

    上节课程回顾: 静态变量:与类无关,不能访问类里的任何属性和方法. 类方法:只能访问类变量. 属性:把一个方法变成静态属性, 反射: __new__:先于__init__执行: __call__: c ...

  5. 推荐一些关于学习Html Css和Js的书吗?

    前端易学易懂,随着移动互联网的日益兴起,it行业对于前端的需求也在不断的提高,那么从前端小白修炼成为前端大神的这个过程之中,一些必备的枕边书也是必不可少的. 第一本,入门<Head first ...

  6. vue企业项目搭建过程(vue-cli脚手架超详细教程 傻瓜-入门)

    vue作为现在主流的前端框架,有必要学习一下. vue的官方文档还是不错的,开源中文,一个爽字形容. 如果不是实际开发需要vue-cli构建项目,那么可以在加一个爽. 然而要构建的时候发现官方文档还是 ...

  7. jenkins构建完成后,执行的命令行的东西也会自动结束的解决办法

    问题: 把添加VPN的指令写在脚本里,然后用jenkins执行这个脚本,jenkins执行的结果是成功的,但是在机器上看,并没有执行成功.   问题分析: 其实在机器上执行过添加VPN的操作,只是在j ...

  8. 洛谷P1443马的遍历

    传送 这是个广搜,思路和普通的迷宫题差不多,但我卡了3遍,为什么呢? 因为输出格式 题目要求左对齐,宽度为5输出,在此说一下如何控制宽度. 下面的m都为要求的宽度 int 类型: printf: %m ...

  9. nginx的启动,停止和重启

    启动 启动代码格式:nginx安装目录地址 -c nginx配置文件地址 例如: [root@LinuxServer sbin]# /usr/local/nginx/sbin/nginx -c /us ...

  10. 高性能mysql 第五章 索引部分总结

    高性能索引 1.索引基础:索引的作用类似'目录'帮助Query来快速定位数据行. 1.1索引类型: 1.1.1 b-tree索引 b-tree(balance tree)索引:使用平衡树(非平衡二叉树 ...