目录
涵盖的主题
安装
MongoDB配置
MongoImport –使用大型数据集初始化数据库
MongoDB – LINQ支持
如何在特定城市中找到要做的事情
运行更快的查询
组项目
接下来
让我们使用.NET Core和MongoDb构建一个简单的WebApi,以查询全球不同目的地的详细信息。我们将使用运行于不同场景的MongoDb LINQ进行搜索。
有关如何使用MongoDB构建和测试完整的.NET CORE WebApi的简要介绍,请查看我之前的文章:将MongoDB .NET驱动程序与.NET Core WebAPI一起使用。
本文继续其他两个部分:
您可以在GitHub上找到该项目:github.com/fpetru/WebApiQueryMongoDb
在本文中,我将使用两个数据集:
使用这些数据集,可以更轻松地运行一些示例查询,以检索一致数量的数据。
这是所有需要安装的东西:
安装MongoDB之后,您将需要配置访问权限以及数据所在的位置。
为此,请在本地创建一个名为mongod.cfg的文件。这将包括设置到MongoDB服务器的数据文件夹以及到MongoDB日志文件的路径,最初不进行任何身份验证(最后两行被注释)。请使用您的本地设置更新这些本地路径:
systemLog:
destination: file
path: "C:\\tools\\mongodb\\db\\log\\mongo.log"
logAppend: true
storage:
dbPath: "C:\\tools\\mongodb\\db\\data"
#Once the admin user is created, remove the comments, and let the authorization be enabled
#security:
# authorization: enabled
在命令提示符下运行。这将启动MongoDB服务器,指向已经创建的配置文件(如果服务器安装在自定义文件夹中,请首先更新命令)
"C:\Program Files\MongoDB\Server\3.4\bin\mongod.exe" --config C:\Dev\Data.Config\mongod.cfg
服务器启动后(您可以在日志文件中看到详细信息),在命令提示符下运行mongo.exe 。下一步是将管理员用户添加到数据库中。使用完整路径(例如:“ C:\Program Files\MongoDB\Server\3.4\bin\mongo.exe”)运行MongoDB,然后将以下代码复制并粘贴到控制台中:
use admin
db.createUser(
{
user: "admin",
pwd: "abc123!",
roles: [ { role: "root", db: "admin" } ]
}
);
exit;
停止服务器,从mongod.cfg文件中取消最后两行的注释,然后重新启动MongoDb服务器。
我们将从Wikivoyage开始。该数据集最初在此处可用(链接)。为了更轻松地导入它,我对其进行了稍微的转换(更改为制表符分隔的文件,并应用了最小限度的数据清理)。该文件位于Github中(链接)。
第二个数据集GeoNames在同一个Github文件夹(链接)中可用。
运行脚本import.bat(与datsets位于同一文件夹中),将导入数据,并创建一个名为TravelDb的新数据库和相关索引。脚本包含在此处,但是最好只运行脚本文件:
mongoimport --db TravelDb ^
--collection WikiVoyage ^
--type tsv ^
--fieldFile enwikivoyage-fields.txt^
--file enwikivoyage-20150901-listings.result.tsv^
--columnsHaveTypes^
--username admin ^
--password abc123! ^
--authenticationDatabase admin ^
--numInsertionWorkers 4
mongoimport --db TravelDb ^
--collection Cities ^
--type tsv ^
--fieldFile cities5000-fields.txt^
--file cities5000.txt ^
--columnsHaveTypes^
--username admin ^
--password abc123! ^
--authenticationDatabase admin ^
--numInsertionWorkers 4
字段文件指定字段名称及其关联的类型。使用optionsHaveTypes选项,我们可以使用所需的类型(例如,int,double,string等)进行导入。
结果应如下所示:
此处包含的.NET Core解决方案采用与我以前的文章(将MongoDB .NET驱动程序与.NET Core WebAPI结合使用)相同的结构。在那里,我已经提供了按步操作指南,内容涉及如何从头开始创建WebApi解决方案,连接到MongoDB以及实现REST API的所有基本操作。
相比之下,此处,Web控制器将仅执行一个操作(GET)–主要集中于运行不同的查询:
[NoCache]
[HttpGet]
public Task> Get()
{
return GetTravelItemsInternal();
}
private async Task> GetTravelItemsInternal()
{
return await _travelItemRepository.GetTravelItems();
}
在后台,查询使用LINQ语法运行,并返回前500条记录。
public async Task> GetTravelItems()
{
try
{
return await _context.TravelItems.Take(500).ToListAsync();
}
catch (Exception ex)
{
// log or manage the exception
throw ex;
}
}
该查询在服务器上呈现,并且我们仅接收有限的数据集。这是可能的,因为我们拥有由MongoDB C#驱动程序本地提供的IQueryable类型接口。
...
using MongoDB.Driver.Linq;
...
public IMongoQueryable TravelItems
{
get
{
return _database.GetCollection("WikiVoyage").AsQueryable();
}
}
假设我们想找到在城市中要做的有趣的事情。我们要么按照动作类型显示城市中的所有物品,要么只选择一个特定的动作(例如,买,做,吃,喝等)。
public async Task> GetTravelItems(string cityName, string action)
{
try
{
if (action != null)
return await _context.TravelItems
.Where(p => p.City == cityName && p.Action == action).ToListAsync();
return await _context.TravelItems.Where(p => p.City == cityName)
.OrderBy(p => p.Action)
.ToListAsync();
}
catch (Exception ex)
{
// log or manage the exception
throw ex;
}
}
该方法将由GET函数调用。假设我们要搜索在巴黎要做的有趣的事情(http://localhost:61612/api/travelquery/Paris?doAction=do),我们会得到有趣的结果,其中一个如下所示:
一种提高查询速度的方法是应用索引。建议在City和Action之后在集合中进行搜索,建议使用这两个字段添加一个简单的索引。
使用mongo shell执行JavaScript文件,将在City上添加索引,然后在Action上添加索引。
db = db.getSiblingDB('TravelDb');
db.WikiVoyage.createIndex( { City: 1, Action: 1 } );
检索速度将从平均0.150毫秒增加到大约0.001毫秒。
如果我们只想看到头条新闻该怎么办?无需详细说明哪些类型的操作可用于特定城市?
一个按城市和操作字段分组的查询示例为:
await _context.TravelItems
.GroupBy(grp => new { grp.City, grp.Action })
.Select(g => new { g.Key.City, g.Key.Action }).ToListAsync();
我将创建本文的第二部分,添加分页支持以及较新的MongoDB版本带来的聚合增强功能,同时还要考虑第二个数据集。也许你知道这些,也许你学到了一些东西。您想看到更多东西吗?