.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 是一 ...
随机推荐
- [Linux]常用命令之【mkdir/touch/cp/rm/ls/mv】
cp 将来源文件夹packageA下的所有目录及文件复制到新文件夹packageB下,形成: /packageB/... # cp -r /home/packageA/* /home/cp/packa ...
- Python property、setter、deleter
面向对象封装特点之一就是通过实现好的方法来访问,限制对数据的不合理访问,把对象状态私有化,仅供类的内部进行操作 下方示例,Test方法的number属性类实例的时候传递1,number是一个公开属性, ...
- IIC总线协议—读写EEPROM
IIC总线协议-读写EEPROM 1.I2C简介 I2C 通讯协议(Inter-Integrated Circuit)是由Phiilps公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要USA ...
- day66:Linux:nginx+uwsgi+django跑python项目
目录 0.uwsgi简述 1.使用uwsgi+django运行demo 2.nginx+uwsgi+django跑pythonav项目 0.uwsgi简述 1.什么是wsgi WSGI,全称Web S ...
- Cesium加载ArcGIS Server4490且orgin -400 400的切片服务
Cesium在使用加载Cesium.ArcGisMapServerImageryProvider加载切片服务时,默认只支持wgs84的4326坐标系,不支持CGCS2000的4490坐标系. 如果是A ...
- Docker的实际应用
一. 数据持久化 我们什么情况下要做数据持久化呢? 一定是在做容器之前先预判好哪些文件是要永久存储的, 而不会跟着它容器的一个生命周期而消失. 比如说配置文件. 日志文件. 缓存文件或者应用数据等等. ...
- 飞行时间技术TOF
文章目录 飞行时间技术TOF 一. 光速的测定 二. 各种TOF技术 直接脉冲TOF 脉冲间接TOF 连续波调制TOF(Continous Wave TOF) 三. TOF技术的应用 飞行时间技术TO ...
- NC19469 01串
题目链接 题目 题目描述 I used to believe We were burning on the edge of something beautiful Something beautifu ...
- 理解 React 中的 useEffect、useMemo 与 useCallback
useEffect 先理解 useEffect 有助于学习 useMemo 和 useCallback.因为 useMemo 和 useCallback 的实现实际上都是基于 useEffect 的. ...
- 2022-09-05:作为国王的统治者,你有一支巫师军队听你指挥。 :给你一个下标从 0 开始的整数数组 strength , 其中 strength[i] 表示第 i 位巫师的力量值。 对于连续的一
2022-09-05:作为国王的统治者,你有一支巫师军队听你指挥. :给你一个下标从 0 开始的整数数组 strength , 其中 strength[i] 表示第 i 位巫师的力量值. 对于连续的一 ...