百度
360搜索
搜狗搜索

mongodb查询语句,MongoDB 查询技巧(1) - 字段相等详细介绍

本文目录一览: MongoDB 查询技巧(2) - null

MongoDB 里面存的 文档, 字段可以 不存在 , 可以 为 null , 可以是 具体的值
在开发过程中,经常需要去 查询某个字段有值的所有文档 , 那么此时怎么写才是正确且简单的呢?

新建一个集合 yu_fa_ce_shi
新增三条数据,如下图所示
a desc 字段为 null
b desc 字段有值,是一个字符串
c desc字段不存在

我们之前 查询有值 的场景是这样写的

功能是正常的

现在我们来研究一下有没有简化的写法

执行之后可以看到,a b 都查询出来了,也就是说
eq(null) 等价于 有值且为null 和 字段不存在 两种场景的并集(也就是 in )

再看一下反向的

执行之后得到结论: ne(null) 等价于 有值且不为null

由上可知 ne(null) 找到的是 有值且不为null , 但是因为 MongoDB 的字段可以随便存,类型没有限制
所以, ne(null) 对取出来的值类型没有做限制
那么,如果想要限制一下,比如: 有值且为 string 这种查询怎么写呢?

经过了解, MongoDB 有一种操作符叫 type type

截图看一下

所以我们的查询语句变为

结果如下,是符合我们预期的

那么问题来了,如何找到 有值且为null 呢?
根据上面的 string , 同理可知

type

mongodb怎么查询数组中的值

肯定可以查到的
mongodb中使用aggregate可以返回数组字段数组的指定索引的元素
参考语句:
{$match:{'duid':15}},
{$project:{duid:1,"default":1}},
{$unwind:"$default.styles"},
{$match:{'default.styles.status':1}},
{$group:{_id:"$_id","defaults":{$push:"$default.styles"}}}
解释:
1:过滤数据{$match:{'duid':15}}
2:获取想要的列{$project:{duid:1,"default":1}}
3:获取展开后数组字段{$unwind:"$default.styles"}
4:条件查询数组元素{$match:{'default.styles.status':1}}
5:分组后保存结果{$group:{_id:"$_id","defaults":{$push:"$default.styles"}}}
数据结构如下:
{
"_id" : ObjectId("55dad346ea23e7c11beefce5"),
"duid" : 11.0,
"default" : {
"style" : "普通会诊",
"alias" : "",
"money" : "0",
"styles" : [{
"code" : 1,
"style" : "普通会诊",
"alias" : "一般会诊",
"money" : 100,
"status" : 1,
"remark" : "需要患者亲自来到医院"
} {
"code" : 6,
"style" : "夜间门诊",
"alias" : "夜间门诊",
"money" : 100,
"status" : 0,
"remark" : "夜间门诊"
}, {
"code" : 7,
"style" : "其他门诊",
"alias" : "其他门诊",
"money" : 10,
"status" : 0,
"remark" : "其他门诊"
}]
}
}

thinkphp6 版本 mongodb 连表查询 案例?

# https://www.cnblogs.com/cangqinglang/p/14858131.html
public function index(){
// 方法1 您可以使用 $toObjectId聚合实现此目的,该聚合仅将字符串ID转换为mongoose objectId
// https://blog.csdn.net/az9996/article/details/110141289
// 多表查询 https://blog.csdn.net/eric_to/article/details/90093806

$pipeline = [
['$addFields'=>['company_id'=>['$toObjectId'=>'$company_id']]],
['$match'=>['$expr'=>['$eq'=>["\$company_id", "$\$company_Id"]]]],
];
$pipelines = [
// ['$match'=>["_id"=>new \MongoDB\BSON\ObjectId("5cb7e580a6c98abc468b458b")]],
// ['$match'=>["name"=>"xxx限公司"]],
[
'$lookup'=>[
'from'=>'oa_company_member_pay',
"let"=>["company_Id"=>"\$_id" ],
"pipeline"=>$pipeline,
'as'=>'company_pay'
],
]
];
// php 执行 产生了 2571 条数据 但是 用 db.runCommand() 执行 打印的 sql 语句 只有 101 条记录
dump(Db::connect('mongo')->name('oa_company')->cmd([
'aggregate'=>'oa_company',
'pipeline'=>$pipelines,
'explain'=>false,
]));
dump(Db::connect('mongo')->getLastSql());

// 以下 mongodb sql 在 数据库 查询 通过 有 2571 条记录
// db.getCollection("oa_company").aggregate([
// {
// "$lookup": {
// "from": "oa_company_member_pay",
// "let": { "company_Id": "$_id" },
// "pipeline": [
// { '$addFields': { "company_id": { "$toObjectId": "$company_id" }}},
// { "$match": { "$expr": { "$eq": [ "$company_id", "$$company_Id" ] } } }
// ],
// "as": "company_member_pay"
// }
// }
// ])
// 以下 mongodb sql 在 数据库 查询 通过 只有 101 条记录
// db.runCommand({
// "aggregate":"oa_company",
// "pipeline":[
// {
// "$lookup":{
// "from": "oa_company_member_pay",
// "let": { "company_Id": "$_id" },
// "pipeline": [
// { '$addFields': { "company_id": { "$toObjectId": "$company_id" }}},
// { "$match": { "$expr": { "$eq": [ "$company_id", "$$company_Id" ] } } }
// ],
// "as": "company_member_pay"
// }
// }
// ],
// "explain":false
// })
// 方法2 或者使用$toString聚合 可以通过 2571
// db.getCollection('oa_company').aggregate([
// { "$addFields": { "companyidStr": { "$toString": "$_id" }}},
// { "$lookup": {
// "from": "oa_company_member_pay",
// "localField": "companyidStr",
// "foreignField": "company_id",
// "as": "pay"
// }}
// ])
/*
$pipelines = [
// ['$match'=>["_id"=>new \MongoDB\BSON\ObjectId("5cb7e580a6c98abc468b458b")]],
// ['$match'=>["name"=>"xxx有限公司"]],
['$addFields'=>['companyidStr'=>['$toString'=>'$_id']]],
[
'$lookup'=>[
'from'=>'oa_company_member_pay',
'localField'=>'companyidStr',
'foreignField'=>'company_id',
'as'=>'company_pay'
],
]
];
// php 执行 产生了 2571 条数据 但是 用 db.runCommand() 执行 打印的 sql 语句 只有 101 条记录
dump(Db::connect('mongo')->name('oa_company')->cmd([
'aggregate'=>'oa_company',
'pipeline'=>$pipelines,
'explain'=>false,
]));
dump(Db::connect('mongo')->getLastSql());

阅读更多 >>>  html+js+按班成绩输入,html写一个学生成绩表

// db.cmd({"aggregate":"oa_company","pipeline":[{"$addFields":{"companyidStr":{"$toString":"$_id"}}},{"$lookup":{"from":"oa_company_member_pay","localField":"companyidStr","foreignField":"company_id","as":"company_pay"}}],"explain":false});

// 下面 执行 不可以 只有 101 条数据
db.runCommand({"aggregate":"oa_company","pipeline":[{"$addFields":{"companyidStr":{"$toString":"$_id"}}},{"$lookup":{"from":"oa_company_member_pay","localField":"companyidStr","foreignField":"company_id","as":"company_pay"}}],"explain":false});
*/
}

mongodb 时间范围查询语句怎么写

你需要有一个字段标示写入数据库的时间,然后查询的时候,设定查询时间段: db.things.find({"createTime":{"$gt":"2014-10-29 0:0:0"}}) // 大于某个时间 db.things.find({"createTime":{"$lt":"2014-10-29 0:0:0"}}) // 小于某个时间

mongodb查询语句怎么合并查询结果

我可以提供一下思路:
用db.coll.find({},{"只显示一列数据,或者几列,越少越好,数据量大了就不好使了,因为后面要排序操作"})$natual:1 排序后,赋值到cursor,然后forEach() 里面用两个变量保存当前一条数据,和上一条数据,直到匹配条件成功,然后就可以返回前后和当前三条数据了。
另外一种办法,是基于上面的,定期 $natual:1出来的数据,追加一列有序数字或者字符,然后保存到另外一张新表,然后根据新表的ID ,查询新表匹配的数据,最后通过查出来的 有序的添加的那列KEY:value 再查询一次前后数据就出来了。

MongoDB 查询技巧(1) - 字段相等

在工作中有时遇到这么一种场景 找出那些字段A和字段B相等的数据
刚开始只能想到自己联表查自己,后面研究了一下,发现了更简单的方法,分享出来

假设我们有以下测试数据

是一张 暗恋表 ,有人喜欢别人,有人自恋
我们现在想要 找出那些自恋的人

lookup语法

根据语法和常规思路,我们写下了如下查询

( $unwind 是用来拍平数据结构的,因为联表之后,嵌套字段是一个列表)

查询之后发现 结果为空
嗯?我们把 match 删了看一下结果是啥

可以看到,联表的确是生效了,但是我们要找的是 自恋 , 而不是 有人爱 ,
联表之后还差一步,就是找到 name 等于 love_yourself.name 的记录
但是,等等,貌似又回到了最初的问题: 找到字段相等的数据
所以,联表也遇到同样的问题,也就是联表并没有解决这个问题,所以此路不通

然后在官方文档的 query 里面找啊找,发现了 expr 的操作,例子很有意思

然后我想,我把 gt 换成 eq 行不行呢
把查询语句换一下

结果如下

bingo! 可以了

这个问题暂时解决了,但是平时工作中,经常遇到 ObjectId 和 String 互相匹配的问题
那么在这种场景下,语句如何写呢?

我们准备好测试数据

值一样的,标记为了同一个颜色

我们先来试一下,思路不变,能不能查出来(语句有变化,字段换成了 _id )

很遗憾,不能

此时还是在 expr 的文档里看到了这么一个例子

很明显, $expr 的 参数列表,参数类型可以是 转换函数,不一定就需要是老老实实的字段, 如图中就是用了 $cond 作为条件函数来转换字段,
那么我把 ObjectId 转为 String 类型的是不是就可以了呢
来试一下以下的查询语句

结果如下

OK,这个场景也解决了

tp5怎么使用mongodb原生语句查询?DB::execute

Db::query() 、Db::execute()这两个函数里面都可以执行原生sql, 不同的是execute()返回的是影响行数,query通常用来做select,返回查询结果;

下面的sql语句对应的MongoDB语句该怎么写?

创建表插入数据
create table a(序号 int,单位 varchar(10),工作 varchar(10),得分 int,打分 varchar(10)) insert into a values (1,'财务','gz1',100,'黎明')insert into a values (2,'财务','gz2',90,'黎明')insert into a values (3,'财务','gz3',80,'黎明')insert into a values (4,'销售','gz4',70,'黎明')insert into a values (5,'销售','gz5',60,'黎明')insert into a values (6,'销售','gz6',50,'黎明')insert into a values (7,'人事','gz7',40,'黎明')insert into a values (8,'人事','gz8',30,'黎明')insert into a values (9,'人事','gz9',20,'黎明')insert into a values (10,'财务','gz1',88,'赵一')insert into a values (11,'财务','gz2',86,'赵一')insert into a values (12,'财务','gz3',78,'赵一')insert into a values (13,'销售','gz4',90,'赵一')insert into a values (14,'销售','gz5',64,'赵一')insert into a values (15,'销售','gz6',85,'赵一')insert into a values (16,'人事','gz7',90,'赵一')insert into a values (17,'人事','gz8',43,'赵一')insert into a values (18,'人事','gz9',68,'赵一')

执行:

select 单位,工作,sum(case when 打分='黎明' then 得分 else 0 end) 黎明,sum(case when 打分='赵一' then 得分 else 0 end) 赵一from a group by 单位,工作

结果:

mongoDB应用篇-mongo聚合查询

如果我们在日常操作中,将部分数据存储在了MongoDB中,但是有需求要求我们将存储进去的文档数据,按照一定的条件进行查询过滤,得到想要的结果便于二次利用,那么我们就可以尝试使用MongoDB的聚合框架。
前面我们在学习文档查询的过程中,也介绍过一些查询的操作符,其中就有一部分是简单的查询聚合函数,例如 count 、 distinct 、 group 等,如果是简单的数据分析过滤,完全可以使用这些自带的聚合函数以及查询的操作符来完成文档的过滤查询操作
如果我们遇到了一些数据需要跨多个文本或者统计等操作,这个时候可能文档自身也较为复杂,查询操作符已经无法满足的时候,这个时候就需要使用MongoDB的聚合查询框架了。
使用聚合框架可以对集合中的文档进行变换和组合查询,基本上我们使用的时候,都是使用多个构件创建一个管道,用于对一连串的文档进行处理。这里的构件包括 筛选(filter) 、 投射(projecting) 、 分组(grouping) 、 排序(sorting) 、 限制(limiting) 以及 跳过(skipping)
MongoDB中需要使用聚合操作,一般使用 aggregate 函数来完成多个聚合之间的连接,aggregate() 方法的基本语法格式如下 :
现在假设我们有个集合articles,里面存储了文章的集合,大致如下:
但这时我们需要查询出来每一个作者写的文章数量,需要使用aggregate()计算 ,大致如下:
输出的结果为:
通过这个简单的案例我们就能输出想要的数据和属性名,大概分析一下刚刚的聚合查询语句, by_user字段进行分组,代表每个用户一条数据,而num_tutorial则是定义了数值类型计算的结果字段,$sum则是计算总和,相当于每个用户出现一次,都会+1,最终计算出来的总和通过num_tutorial字段进行输出
注:如果管道没有给出预期的结果,就需要进行调试操作,调试的时候,可以尝试先给一个管道操作符的条件,如果这个时候查询出来的结果是我们想要的,那么我们需要再去指定第二个管道操作符,依次操作,最后就会定位到出了问题的操作符
前面我们提到聚合查询会使用管道操作符,而每一个操作符就会接受一连串的文档,对这些文档进行一些类型转换,最后将转换以后的文档结果传递给下一个管道操作符来执行后续的操作,如果当前是最后一个管道操作符,那么则会显示给用户最后的文档数据。不同的管道操作符是可以按照顺序组合在一起使用,并且可以被重复执行多次,例如我们可以先使用$match然后再去、 match操作。
match管道操作符可以使用$gt、$lt、$in等操作符,进行过滤,不过需要注意的是不能在$match管道操作符中使用空间地理操作符。
在实际使用的过程中,尽可能的将 match操作符以后,再去投射或者执行分组操作的话,是可以利用索引的。
相比较一般的查询操作而言,使用管道操作,尤其是其中的投射操作更加强大。我们可以在查询文档结束以后利用 $project 操作符从文档中进行字段的提取,甚至于我们可以重命名字段,将部分字段映射成我们想要展示出去的字段,也可以对一部分字段进行一些有意义的处理。需要注意的是, $project 操作符可以传入两个参数,第一个是需要处理的属性名称,第二个则是0或者1,如果传入1,则代表当前的属性是需要显示出来的,如果是0或者不写,默认都是代表这个字段不需要显示出来
当然第二个参数也可以是一个表达式或者查询条件,满足当前表达式的数据也可以进行显示,接下来我们先准备一点数据:
接下来,我们来查询,条件是item字段为abc,quantity要大于5,并且我们只要item和price字段的结果,其他都排除掉:
可以看到结果为:
如果我们想要在原基础上改变某个字段的名称,例如将item改为item_code,可以利用$来完成,如下:
可以看到我们指定的名称item_code,而这个别名对应的字段item使用$作为前缀标记,代表将item字段映射为item_code,可以看到结果:
我们在投影的时候,除了可以将某个字段映射成其他字段以外,还可以针对某个字段进行一些简单的运算,最常见的就是 四则运算 ,即
加法( subtract )、乘法( divide )、求模( $mod ) ,
除此之外,还支持对字段进行 关系运算 (大小比较( " eq" )、大于( " gte" )、小于( " lte" )、不等于( " ifNull" ) )、
逻辑运算 (与( " or" )、非 ( " concat" )、截取( " toLower" ) )等
我们基于上面的需求,假设每一个价格是按照元为单位,现在要求输出W为单位,那么我们就需要对price进行除法运算,如下:
除此之外,我们也可以将计算完毕的price改名为priceW,即:
可以看到输出的结果为:
这时有一个需求,要求我们返回数据的同时还要yyyy-MM-dd格式的时间字符串,这个时候我们就需要对date字段进行时间函数和字符串混合处理了,如下:
这里需要注意的一点是, year:" substr函数将date字段的结果截取成字符串即可实现拼接
group的_id上,代表按照当前字段进行分组,例如,我们这里根据item进行分组:
在我们针对某个字段进行分组以后,我们可以针对每个分组进行一些操作符的使用,常见的例如: $sum 、 $avg 、 $min 、 $max 、 $first 、 $last 。
$avg 操作符用来返回每一个分组内的平均值
现在我们基于前面item的分组,我们想要算出来每个组内的平均价格是多少,如下:
$min 和 $max 操作符用于返回分组内最大的值和最小的值
除了平均值以外,我们现在将最贵的和最便宜的价格也要列出来,这个时候就可以使用这两个操作符了,如下:
$first 、 $last 则是可以获取当前分组中第一个或者最后一个的某个字段的结果,如下:
除此之外,我们还可以在分组的时候使用数组操作符,例如 $addToSet 可以判断,当前数组如果不包含某个条件,就添加到当前数组中, $push 则不管元素是否存在,都直接添加到数组中
注意:大部分管道操作符都是流式处理的,只要有新的文档进入,就可以对新的文档进行处理,但是 $group 代表必须收到全部文档以后才可以进行分组操作,才会将结果传递给后续的管道操作符,这就意味着,如果当前mongo是存在分片的,会先在每个分片上执行完毕以后,再把结果传递mongos进行统一的分组,剩下的管道操作符也不会在每个分片,而是mongos上执行了
如果我们现在遇到一些文档比较复杂,比如存在内嵌文档的存在,某个属性里面嵌套了一个数组,但是我们需要对内嵌的数组文档进行分析过滤等查询处理,这个时候就可以使用 $unwind 操作符将每一个文档中的嵌套数组文件拆分为一个个独立的文档便于进行后续的处理,例如我们需要将之前的set集合中关于请求的url以及ip的信息拆分出来,原始的格式如下:
我们可以使用命令进行拆分,如下:
结果为:
可以看到数据则是按照每一条信息的方式展示出来了,方便后续的计算以及输出,但是需要注意的一点是,这种方式,如果该文档中没有拆分的字段,或者是空数组,默认会直接排除,如果我们需要空数组等也输出计算出来,则可以指定 preserveNullAndEmptyArrays 参数,设置为true,则代表空数组或者不存在的文档也要拆分输出出来,即:
我们可以在管道查询的过程中,按照某个属性值或者多个属性的结果进行顺序排序,排序的方式与普通查询操作符中的sort操作符表现一致,与其他管道操作符一样,可以在任何阶段使用,但是,需要注意的一点是,建议在管道操作符第一阶段进行排序,因为此时的排序是可以触发索引的,如果在后续阶段进行排序,会消耗大量内存,并且耗时会很久,尤其是在有 $group 的情况下,如果放在 $group 操作符后面,会发现等到的时间很久,不仅仅是无法触发索引的问题,还和 $group 操作符是等待所有数据完毕才会触发的特性有关,因此需要格外注意。
结果如下,按照我们想要的结果进行了排序:
limit,只返回前两条数据,如下:
结果如下:
除了 skip,与之前的查询操作符作用也是一样的,用于在已经查询完毕的结果集中跳过前N条数据以后进行返回,我们将$skip加在刚刚的查询后面,如下:
这个时候可以看到返回的结果为空,什么结果都没有了,这是因为前一步管道已经限制了仅仅返回2条,而接着我们又跳过了前两条文档,因此返回的结果为空,我们将顺序调换一下,看看:
可以看到结果如下,与刚才的结果无异:
管道查询操作符有很多,除了上面学习的常用的部分,还有几十个,需要了解全部的可以参考官网:
https://docs.mongodb.com/manual/reference/command/aggregate/
除此之外,我们在学习的过程中了解到,部分查询操作符是可以触发索引的,例如 $project 、 $group 或者 $unwind 操作符,因此我们也建议 如果可以的话,尽量先使用这类管道操作符进行数据过滤,可以有效减少数据集大小和数量,而且管道如果不是直接从原先的集合中使用数据,那就无 法在筛选和排序中使用索引 ,例如我们先进行管道操作,再去将过滤好的数据进行 $sort 排序,会导致无法使用索引,效率大幅度下降,因此如果我们需要涉及到 $sort 操作的时候,如果可以尽可能在最开始就处理,这个时候可以使用索引,效率较高,然后再去进行管道查询筛选与分组等其他操作,可以有效的提高查询的效率。另外需要注意的一点是,在 MongoDB中会对每一个管道查询做限制,例如某一步管道查询操作导致内存占用超过20%,这个时候就会报错,无法继续使用管道 ,因为mongoDB本身每次最大是16Mb的数据量,为了尽可能避免或者减少这种问题,建议可以考虑尽可能的使用 $match 操作符过滤无用数据,减少数据总大小。同时也 因为管道查询是多步执行,例如 $group 则是等待所有数据完毕才会执行,因此可能会导致整体执行时间较久 ,也因为这样,才不建议在较高的实时查询需求上使用管道和查询,而是在 设计的时候尽可能直接使用查询操作符进行数据查询,触发更多的索引,更快的销量查询出来想要的结果。

阅读更多 >>>  手机通话记录可以查询吗

网站数据信息

"mongodb查询语句,MongoDB 查询技巧(1) - 字段相等"浏览人数已经达到21次,如你需要查询该站的相关权重信息,可以点击进入"Chinaz数据" 查询。更多网站价值评估因素如:mongodb查询语句,MongoDB 查询技巧(1) - 字段相等的访问速度、搜索引擎收录以及索引量、用户体验等。 要评估一个站的价值,最主要还是需要根据您自身的需求,如网站IP、PV、跳出率等!