.Net下验证MongoDB 的 Linq 模式联合查询是否可用
MongoDB.Driver 类库提供了 Linq 查询的支持。然而,在使用 Linq 进行联合查询时,是否能够正确转换为 MongoDB 底层的查询语句还有待验证。今天,我将进行实验来验证一下。
输出查询语句
首先,通过订阅 MongoClientSettings 的功能,将查询语句输出。
var settings = MongoClientSettings.FromConnectionString("mongodb://192.168.11.137:27017");
settings.ClusterConfigurator = cb => {
cb.Subscribe<CommandStartedEvent>(e =>
{
Debug.WriteLine( e.Command.ToString());
});
};
接下来,实例化 MongoClient 对象。由于我准备测试三个集合的联合查询,所以初始化了三个集合对象,并将它们转换为 Queryable 类型,以便使用 Linq 语句进行查询。
var client = new MongoClient(settings);
var database = client.GetDatabase("MyTestDB");
var userinfos = database.GetCollection<UserInfo>("UserInfo").AsQueryable();
var ages = database.GetCollection<UserAge>("UserAges").AsQueryable();
var ageinfos = database.GetCollection<AgeInfo>("AgeInfos").AsQueryable();
简洁版联合查询
先尝试直接使用 SelectMany 查询,看是否支持联合查询。
记得先使用 MongoDB.Driver.Linq 命名空间,否则会报错。
var data = (from u in userinfos
from a in ages
where u.Id == a.UserId
select u).FirstOrDefault();
运行代码后,data 对象是有值的。实际输出的查询语句如下:
{ "aggregate" : "UserAges", "pipeline" : [], "cursor" : { }, "$db" : "MyTestDB", "lsid" : { "id" : CSUUID("f8e45203-f268-4fe1-9adf-b1071b3baa1f") } }
{ "aggregate" : "UserInfo", "pipeline" : [{ "$project" : { "_v" : { "$map" : { "input" : [{ "_id" : ObjectId("64a264055a5c1963f4f330a0"), "UserId" : ObjectId("6470620ab45534bbc84d41ec"), "Name" : "Jack", "Age" : 0 }], "as" : "a", "in" : { "u" : "$$ROOT", "a" : "$$a" } } }, "_id" : 0 } }, { "$unwind" : "$_v" }, { "$match" : { "$expr" : { "$eq" : ["$_v.u._id", "$_v.a.UserId"] } } }, { "$project" : { "_v" : "$_v.u", "_id" : 0 } }], "cursor" : { }, "$db" : "MyTestDB", "lsid" : { "id" : CSUUID("f8e45203-f268-4fe1-9adf-b1071b3baa1f") }, "$clusterTime" : { "clusterTime" : Timestamp(1688436977, 1), "signature" : { "hash" : new BinData(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } } }
对于了解 MongoDB 的人来说,可以看出这并不是 MongoDB 的联合查询语句。它实际上是首先将一个表的数据取出,然后与另一个表进行比较。因此,这种方法不能用于联合查询。
Join查询
接下来,我们来看看 Join 查询的语句是什么样的。
var datas = (from u in userinfos
join a in ages on u.Id equals a.UserId into aGroup
from a2 in aGroup.DefaultIfEmpty()
select new {
User = u,
Age = a2
}).FirstOrDefault();
输出的查询语句如下:
{ "aggregate" : "UserInfo", "pipeline" : [{ "$project" : { "_outer" : "$$ROOT", "_id" : 0 } }, { "$lookup" : { "from" : "UserAges", "localField" : "_outer._id", "foreignField" : "UserId", "as" : "_inner" } }, { "$project" : { "u" : "$_outer", "aGroup" : "$_inner", "_id" : 0 } }, { "$project" : { "_v" : { "$map" : { "input" : { "$let" : { "vars" : { "source" : "$aGroup" }, "in" : { "$cond" : { "if" : { "$eq" : [{ "$size" : "$$source" }, 0] }, "then" : [{ "_id" : ObjectId("000000000000000000000000"), "UserId" : ObjectId("000000000000000000000000"), "Name" : null, "Age" : 0 }], "else" : "$$source" } } } }, "as" : "a2", "in" : { "User" : "$u", "Age" : "$$a2" } } }, "_id" : 0 } }, { "$unwind" : "$_v" }, { "$limit" : NumberLong(1) }], "cursor" : { }, "$db" : "MyTestDB", "lsid" : { "id" : CSUUID("7eb2b612-b037-430e-b86c-4f349112ba56") } }
这个查询语句看起来是比较标准的 MongoDB 联合查询了。再多加一个表进行 Join 查询,看看输出的语句。
var datas = (from u in userinfos
join a in ages on u.Id equals a.UserId into aGroup
from a2 in aGroup.DefaultIfEmpty()
join info in ageinfos on a2.Id equals info.AgeId into bGroup
from info2 in bGroup.DefaultIfEmpty()
select new {
User = u,
Age = a2,
Info = info2
}).FirstOrDefault();
输出查询语句:
{ "aggregate" : "UserInfo", "pipeline" : [{ "$project" : { "_outer" : "$$ROOT", "_id" : 0 } }, { "$lookup" : { "from" : "UserAges", "localField" : "_outer._id", "foreignField" : "UserId", "as" : "_inner" } }, { "$project" : { "u" : "$_outer", "aGroup" : "$_inner", "_id" : 0 } }, { "$project" : { "_v" : { "$map" : { "input" : { "$let" : { "vars" : { "source" : "$aGroup" }, "in" : { "$cond" : { "if" : { "$eq" : [{ "$size" : "$$source" }, 0] }, "then" : [{ "_id" : ObjectId("000000000000000000000000"), "UserId" : ObjectId("000000000000000000000000"), "Name" : null, "Age" : 0 }], "else" : "$$source" } } } }, "as" : "a2", "in" : { "<>h__TransparentIdentifier0" : "$$ROOT", "a2" : "$$a2" } } }, "_id" : 0 } }, { "$unwind" : "$_v" }, { "$project" : { "_outer" : "$_v", "_id" : 0 } }, { "$lookup" : { "from" : "AgeInfos", "localField" : "_outer.a2._id", "foreignField" : "AgeId", "as" : "_inner" } }, { "$project" : { "<>h__TransparentIdentifier1" : "$_outer", "bGroup" : "$_inner", "_id" : 0 } }, { "$project" : { "_v" : { "$map" : { "input" : { "$let" : { "vars" : { "source" : "$bGroup" }, "in" : { "$cond" : { "if" : { "$eq" : [{ "$size" : "$$source" }, 0] }, "then" : [{ "_id" : ObjectId("000000000000000000000000"), "AgeId" : ObjectId("000000000000000000000000"), "CreateTime" : ISODate("0001-01-01T00:00:00Z") }], "else" : "$$source" } } } }, "as" : "info2", "in" : { "User" : "$<>h__TransparentIdentifier1.<>h__TransparentIdentifier0.u", "Age" : "$<>h__TransparentIdentifier1.a2", "Info" : "$$info2" } } }, "_id" : 0 } }, { "$unwind" : "$_v" }, { "$limit" : NumberLong(1) }], "cursor" : { }, "$db" : "MyTestDB", "lsid" : { "id" : CSUUID("bb4e2da5-bedb-4a8e-b1f0-92e5889bc71d") } }
通过三表联合查询,lookup 了两次,应该是正确的。不过里面是否有一些无用并且会影响性能的语法,熟悉 MongoDB 语法的朋友可以来发表一下意见。
.Net下验证MongoDB 的 Linq 模式联合查询是否可用的更多相关文章
- linq中如何实现多个条件的联合查询
目前接触处理数据这一块比较多,在处理内存中的数据源的时候我一般使用的是linq,linq使用起来像sql语句一样,用法简单,功能强大. 最近需要实现一个从两个不同的文件读取不同的数据,然后根据这两个数 ...
- .NET平台下使用MongoDB入门教程
适合人群:完全没有接触MongoDB或对MongoDB有一点了解的C#开发人员.因为本文是一篇入门级的文章. 一.了解MongoDB MongoDB是一个基于分布式文件存储的数据库.由C++语言编写 ...
- 转 【.NET平台下使用MongoDB入门教程】
目录 一.了解MongoDB 二.MongoDB特点 三.安装及常用命令 3.1 下载安装 3.2 启动服务器 3.3 常用操作 3.4 其他命令 3.5 做成windows服务 四.批处理程序开启M ...
- centos7下搭建 MongoDB -01
距离上次写的一篇mongoDB搭建已经有一年多的时间了,刚好这次在公司搭建好在centos7下的mongodb搭建,简单的做一个记录吧 mongo 是一个基于分布式文件存储的数据库,数据主要存储在磁盘 ...
- 单机Linux下搭建MongoDB副本集-三节点
前言说明 Linux下安装MongoDB副本集我基本上是一次搭建,几百年不再碰,也记不住具体的命令,偶尔需要搭建都是直接网上找的教程. 有些教程很精简,有些又版本不一样,所以索性我整合下别人的教程,把 ...
- MongoDB学习笔记—Linux下搭建MongoDB环境
1.MongoDB简单说明 a MongoDB是由C++语言编写的一个基于分布式文件存储的开源数据库系统,它的目的在于为WEB应用提供可扩展的高性能数据存储解决方案. b MongoDB是一个介于关系 ...
- centos7 下安装MongoDB
查看MongoDB的最新版官方下载地址: https://www.mongodb.com/download-center#community 使用wget命令下载安装包 wget https://fa ...
- Mongodb联合查询
Mongodb使用联合查询的重点需要添加@DBref 这样的话不会将整个文档保存,只会保存关联集合的id package com.java.web; import java.util.List; i ...
- windows下安装MongoDB扩展和配置
windows下安装MongoDB扩展和配置 1.下载mongoDB扩展,根据当前php版本进行下载 地址如下:http://pecl.php.net/package/mongo 我本地php版本是 ...
- Linux下的Mongodb部署应用梳理
一.Mongodb简介 官网地址:http://www.mongodb.org/ MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数据库中比较热门的一种.MongoDB 是一 ...
随机推荐
- [网络]公共网络安全漏洞库: CVE / CNCVE
本文博主的经历与该博文处理绿盟科技安全评估的系统漏洞 - 博客园的经历相同: 处理[第三方网络安全公司]给[公司产品]的[客户的服务器]扫描后生成的[安全漏洞报告]. 1 前言 以网络安全行业中最大的 ...
- 四月二十一号Java知识基础
1.接口本身具有数据成员.抽象方法.默认方法.和静态方法,但它与抽象类不同 1)接口的数据成员都是静态的且必须初始化,即数据成员必须是静态常量 2)接口中除咯声明抽象方法外,还可以定义静态方法 和默认 ...
- OpenJudge 1.8编程基础之多维数组
04:错误探测 1.描述 给定n*n由0和1组成的矩阵,如果矩阵的每一行和每一列的1的数量都是偶数,则认为符合条件.你的任务就是检测矩阵是否符合条件,或者在仅改变一个矩阵元素的情况下能否符合条件.&q ...
- c/c++快乐算法第二天
c/c++感受算法乐趣(2) 开始时间2023-04-15 22:26:49 结束时间2023-04-16 00:18:16 前言:首先我们来回忆一下昨天接触了些什么算法题,1.1百钱百鸡问题,1.2 ...
- Cmder: 懒癌必备!从此告别记事本记命令的日子
前言 平时开发中遇到这样那样的命令需要记下来,一般做法是这样. 新建记事本 将需要记下的关键命令保存. 每次需要使用时,粘贴复制即可. 好像没什么毛病!直到遇到了 Cmder... 当看到同事分析问题 ...
- web 页面/内容 触摸/点击滑动
监听标签的触摸/鼠标滑动事件,添加元素的切换动画,效果如下: 事件监听 鼠标事件和触摸事件监听: 1 componentDidMount() { 2 var teachingReportDiv = d ...
- Python 使用列表一部分(切片)
使用列表的一部分(切片) 处理列表的部分元素 切片 指定第一个元素的索引和最后一个元素索引加1 列表名[索引:索引+1] 索引加1:列表中第索引个元素 (左包括右不包括) 未指定索引 列表名[:] 提 ...
- python 编程规范有哪些?
Python 编程规范主要包括代码布局.命名规范.注释规范.函数编写规范等多个方面,下面给出一些常见的编程规范及其示例代码. 1. 代码布局规范 代码布局规范主要是指代码的缩进.行宽.空行.换行等方面 ...
- 一文搞懂 x64 IA-64 AMD64 Inte64 IA-32e 架构之间的关系
想要搞清楚 x64.IA64.AMD64 指令集之间的关系,就要先了解 Intel 和 AMD 这两家公司在生产处理器上的发展历史. x86 处理器 1978年 Intel 生产了它的第一款 16bi ...
- 【故障补牢】贪吃的 Bing 爬虫,限量供应的应对措施
相对于[故障公告],[故障补牢]分享的是园子在发生故障后采取的亡羊补牢措施. 在上次被微软 Bing 爬宕机后(详见 [故障公告]被放出的 Bing 爬虫,又被爬宕机的园子),我们采取了2个应对措施, ...