.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 是一 ...
随机推荐
- [网络/Java EE/Web]Tomcat/Nginx中配置全局的安全响应头(header)——X-Frame-Options / X-XSS-Protection / X-Content-Options
Step1 配置Tomcat step1.1 查看是否已配置目标的HTTP网络安全头 方式1 – Tomcat / conf/web.xml cat /opt/myTomcat/conf/web.xm ...
- [GIT]辨析/区别: git reset HEAD 与 git reset --hard HEAD | 版本回撤
1 场景1: 撤销到远程仓库或本地仓库的最新最近一次的正式版本 1.1 文由 时常有这样一种场景,不小心改动了部分文件,或修改了部分文件却发现无用,此时可能还没有git push,也可能push了:又 ...
- [Spring MVC]@RequestMapping 与 @RequestMapping+@RequestResponse的区别
假定:返回格式均为JSON,JSON实体对象myJson的属性有:data.message.code.status. 二者的区别在于: @RequestMapping:会在最外层包裹 data属性,将 ...
- 四月二十一号Java知识基础
1.接口本身具有数据成员.抽象方法.默认方法.和静态方法,但它与抽象类不同 1)接口的数据成员都是静态的且必须初始化,即数据成员必须是静态常量 2)接口中除咯声明抽象方法外,还可以定义静态方法 和默认 ...
- 实时分布式低延迟OLAP数据库Apache Pinot探索实操
@ 目录 概述 定义 特性 何时使用 部署 Local安装 快速启动 手动设置集群 Docker安装 快速启动 手动启动集群 Docker Compose 实操 批导入数据 流式导入数据 概述 定义 ...
- 循序渐进的掌握uni-app,两个小时完成一个简单项目——新闻App、新闻小程序
效果图 一.创建项目 uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS.Android.Web(响应式).以及各种小程序(微信/支付宝/百度/头条/ ...
- 借助 APISIX Ingress,实现与注册中心的无缝集成
作者张晋涛,API7.ai 云原生技术专家,Apache APISIX PMC 成员,Apache APISIX Ingress Controller 项目维护者. 原文链接 云原生场景下是否需要服务 ...
- CSP2022 游记
前言 本人坐标 HN,因为本人太菜了所以这次考得差的一批请见谅-- 7:30 老爸开车送我到 SDFZ 门口,遇到了 @_SunLight_,然后他拼命跟我叫"要寄了"结果我们俩真 ...
- dp杂题选做
树的数量 题目其实挺简单的,难点在于状态的设计(其实也没多难). 令 \(f_i\) 表示 \(i\) 个点的 \(m\) 叉树的数量,发现无法转移.设 \(g_{i,j}\) 表示根节点所在子树内有 ...
- 音视频八股文(8)-- h264 AnnexB
NALU(Network Abstract Layer Unit) ⾳视频编码在流媒体和⽹络领域占有重要地位:流媒体编解码流程⼤致如下图所示: H264简介 H.264从1999年开始,到2003年形 ...