如何搜索旅行的好地方(MongoDb LINQ和.NET Core)

目录

涵盖的主题

安装

MongoDB配置

MongoImport –使用大型数据集初始化数据库

MongoDB – LINQ支持

如何在特定城市中找到要做的事情

运行更快的查询

组项目

接下来


让我们使用.NET CoreMongoDb构建一个简单的WebApi,以查询全球不同目的地的详细信息。我们将使用运行于不同场景的MongoDb LINQ进行搜索。

有关如何使用MongoDB构建和测试完整的.NET CORE WebApi的简要介绍,请查看我之前的文章:将MongoDB .NET驱动程序与.NET Core WebAPI一起使用

本文继续其他两个部分:

您可以在GitHub上找到该项目:github.com/fpetru/WebApiQueryMongoDb

在本文中,我将使用两个数据集:

  • Wikivoyage提供了全球最受旅行者欢迎的博物馆、景点、餐厅和酒店的更多详细信息。原始数据集可以从下一个url访问。
  • 第二个数据集来自GeoNames,它是一个覆盖所有国家的地理数据库。出于演示目的,我只选择了人口超过5000的城市。

使用这些数据集,可以更轻松地运行一些示例查询,以检索一致数量的数据。

涵盖的主题

  • MongoDb –安装和安全设置
  • MongoDB –使用mongoimport工具
  • 制作一个完整的ASP.NET WebApi项目,使用MongoDB C#Driver v.2异步连接
  • 运行LINQ查询

安装

这是所有需要安装的东西:

MongoDB配置

安装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服务器。

MongoImport –使用大型数据集初始化数据库

我们将从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选项,我们可以使用所需的类型(例如,intdoublestring等)进行导入。

结果应如下所示:

MongoDB – LINQ支持

此处包含的.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),我们会得到有趣的结果,其中一个如下所示:

https://i0.wp.com/www.qappdesign.com/wp-content/uploads/2017/04/query-city-action-2.jpg?zoom=1.25&w=960

运行更快的查询

一种提高查询速度的方法是应用索引。建议在CityAction之后在集合中进行搜索,建议使用这两个字段添加一个简单的索引。

使用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版本带来的聚合增强功能,同时还要考虑第二个数据集。也许你知道这些,也许你学到了一些东西。您想看到更多东西吗?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
操作monodb的c#封装,调用非常方便,可以继承,功能包括: 1、所有数据库操作 2、前台表格类数据获取 public List GetList(List lstColName, Document query, JqGridParam jqParam, ref int count),封装了通用的获取前台表格数据的方法,将在工程中减少大量数据库访问代码,有了这个后对前台表格类查询我们可以不用在Control里使用linq或者封装在Model里然后对前台定义视图类了,使用如下: try { JqGridParam jqParam = new JqGridParam(); jqParam.page = 1; jqParam.rows = 1000; MemberOper memOper = new MemberOper(); MongoBasicOper monOper = new MongoBasicOper(DTName.GROUP_MEMBER); int count = 0; //过滤条件 Document query = new Document(); if (!string.IsNullOrEmpty(find)) { MongoRegex reg = new MongoRegex(".*" + find + ".*"); query.Add(DColName.Name, reg); } query.Add(DColName.GroupId, g); Document[] docStatus = new Document[] { new Document(DColName.Status, RowStatus.Pass), new Document(DColName.Status, RowStatus.Admin) }; query.Add("$or", docStatus); //查询列 List lstColName = new List(); lstColName.Add(DColName.UserId); lstColName.Add(DColName.UserName); //查询数据 var lstRes = monOper.GetListEx(lstColName, query, jqParam, ref count); //转换返回值 JqGrid jg = new JqGrid(); if (count == 0) { return Json(jg.toNull(jqParam), JsonRequestBehavior.AllowGet); } var jsonData = jg.toJson(jqParam, count, lstRes, lstColName); jsonData.param = g; return Json(jsonData, JsonRequestBehavior.AllowGet); } catch (Exception e) { return Json(e.Message, JsonRequestBehavior.AllowGet); }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值