65.9K
CodeProject 正在变化。 阅读更多。
Home

MongoDB 版本 2 某些操作

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4投票s)

2016年3月3日

CPOL

4分钟阅读

viewsIcon

13622

MongoDB 版本 2 驱动程序的 CRUD 及其过滤功能

引言

互联网上有很多关于如何使用 MongoDB 驱动程序版本 1 的手册,但关于版本 2 的不多。我想补充一些关于使用版本 2 的信息。

那么,让我们从读取开始

在 MongoDB 中,读取可以被认为是以下选项

  1. 查找所有文档
  2. 过滤
  3. 排序
  4. 定义和构建器

在 MongoDB 中创建文档很简单。您可以使用 Insert(字母 C)来完成。

在这里,您有很多选项

  1. 替换
  2. 更新
  3. Upsert(更新插入)

我还要提到删除,或者字母 D。

另外,我想描述如何使用 projections(投影)来限制您从 MongoDB 中获取的内容。

那么,让我们从在 MongoDB 中同步查找一些信息开始。

假设我有以下类声明

public abstract class MongoEntityBase
    {
        // ReSharper disable once InconsistentNaming
        public ObjectId _id { get; set; }
    }
 
    public class SampleClarification : MongoEntityBase
    {
        public ObjectId SomeId { get; set; }
        public int RectificationNumber { get; set; }
        public string RectificationReason { get; set; }
        public string RectificationText { get; set; }
    }

这个类将使我可以操作 MongoDB 数据库中的 SampleClarification 集合。

另外,请看 MongoDB 的数据库上下文的默认构建

public class SampleDataContext
    {
        public IMongoDatabase Database;
 
        public SampleDataContext()
        {
            var client = new MongoClient("https://:27017/sample");
            Database = client.GetDatabase("sample");
        }
    }

为了**同步**获取这个集合,我需要向 datacontext 添加接口集合。数据上下文将被转换为这样

public class SampleDataContext
    {
        public IMongoDatabase Database;
        public SampleDataContext()
        {
            var client = new MongoClient("https://:27017/sample");
            Database = client.GetDatabase("sample");
        }
        public IMongoCollection<SampleClarification> 
        SampleClarifications => Database.GetCollection<SampleClarification>("sample");
    }

这里最重要的部分是 SampleClarifications

然后,您可以用以下方式搜索所有 SampleClarifications

SampleDataContext sc = new SampleDataContext();
var allDocs = sc.SampleClarifications.Find(new BsonDocument()).ToList();

然后,allDocs 将在内存中列出所有文档。

所以,那是一个同步调用。

现在我想演示一个异步调用(这将像蛋糕一样简单)

SampleDataContext sc = new SampleDataContext();
var allDocs = await sc.SampleClarifications.Find(new BsonDocument()).ToListAsync();

但是,假设您想遍历返回的文档,并对它们做一些事情。那么函数 ForEachAsync 非常方便。我建议将其与 cursor(游标) 一起使用。

接下来是过滤。过滤的一种方法如下

SampleDataContext sc = new SampleDataContext();
            var allDocs = await sc.SampleClarifications.Find(new BsonDocument()
                    {
                        { "RectificationNumber" , 4}
                }
                ).ToListAsync();

您是否觉得使用字符串进行过滤不是一个好方法?如果是,您并不孤单。 MongoDB 驱动程序有一些用于过滤的新功能

SampleDataContext sc = new SampleDataContext();
           
var allDocs = await sc.SampleClarifications.
              Find(Builders<SampleClarification>.Filter.Gte
              (a => a.RectificationNumber, 7)).ToListAsync();

读取过滤器创建的一种方法可以是:构建一个 SampleClarification 类型的过滤器,该过滤器返回 SampleClarification 实例,其中 RectificationNumber 大于或等于 7。

其他可能性可以是 Lte - 小于等于,Eq - 等于,等等。

另一个有用的功能是使用 Where。例如,像这样

SampleDataContext sc = new SampleDataContext();
            
var allDocs = await sc.SampleClarifications.
              Find(Builders<SampleClarification>.Filter.Where
              (a => a.RectificationNumber == 7)).ToListAsync();

IMHO where 适用于您不想记住 Lte、Eq、Gte、Ne 等的情况。**但是 Where 有一个重要的特性。您可以在那里传递可空值。**

MongoDB 的另一个有趣的特性是组合过滤特性。见以下代码

SampleDataContext sc = new SampleDataContext();
 
var filter = Builders<SampleClarification>.Filter.Empty;
 
if (true /*some condition*/)
{
     filter = filter & Builders<SampleClarification>.Filter.Where
              (a => a.RectificationText.Contains("aaa"));
}
 
var allDocs = await sc.SampleClarifications.Find(filter).ToListAsync();

很有趣,是吧?当我看到 & 而不是 && 时,我很惊讶。

但这还不是全部。让我向您介绍另一个快捷方式:&=。像这样

if (true /* another condition */)
{
      filter &= Builders<SampleClarification>.Filter.Gte(a => a.RectificationNumber, 20);
}

排序

对于排序,您可以再次使用 Builder。可以像这样实现

SampleDataContext sc = new SampleDataContext();
 
var filter = Builders<SampleClarification>.Filter.Empty;
var sorting = Builders<SampleClarification>.Sort.Ascending(t => t.RectificationNumber);
var allDocs = await sc.SampleClarifications.Find(filter).Sort(sorting).ToListAsync();

如果您觉得为了 Sort 某些东西而输入大量内容很无聊,您可以查看 SortBy 函数

SampleDataContext sc = new SampleDataContext();
var filter = Builders<SampleClarification>.Filter.Empty;
var allDocs = await sc.SampleClarifications.Find(filter).SortBy
              (s => s.RectificationNumber).ToListAsync();

或者您可以使用更复杂的模式

SampleDataContext sc = new SampleDataContext();
var filter = Builders<SampleClarification>.Filter.Empty;
var allDocs = await sc.SampleClarifications.Find(filter).
              SortBy(s => s.RectificationNumber)
              .ThenByDescending(a => a.TenderId)
              .ThenBy(a => a.RectificationReason).ToListAsync();

插入,或 CRUD 中的 C

您可以插入一个元素或多个元素。这是一个如何创建一个的例子

SampleDataContext sc = new SampleDataContext();
var filter = Builders<SampleClarification>.Filter.Empty;
var clar = new SampleClarification();
clar.RectificationNumber = 10;
clar.RectificationReason = "some reason";
clar.RectificationText = "fasdfdas fdsfas";
await sc.SampleClarifications.InsertOneAsync(clar);

替换,或 CRUD 中几乎是 U 的操作

首先,什么是替换。 Replace 是指您找到文档,删除它,然后放入一个具有修改值的新文档。

首先,您需要找到元素,然后 update 其值,然后保存它。这是一个例子

SampleDataContext sc = new SampleDataContext();
//var filter = Builders<SampleClarification>.Filter.Where
//(r => r.TenderId == ObjectId.Parse("56d55f1d4ee6bc45a0d7b539"));
//var clar = sc.SampleClarifications.Find(filter).FirstOrDefault();
 
//or another way:
var clar =  sc.SampleClarifications.Find(a => a.TenderId == ObjectId.Parse
            ("56d55f1d4ee6bc45a0d7b539")).FirstOrDefault();
 
if (clar != null)
{
    sc.SampleClarifications.ReplaceOne(r => r._id == clar._id, clar);
}

Replace one 将搜索条件作为参数,并将替换传递的元素。

CRUD 中的 U 或更新

好吧,要进行 update,您需要带有更新策略的 Builder。参见代码示例

SampleDataContext sc = new SampleDataContext();
 
var text = "fasfds afasfas";
var clar =  sc.SampleClarifications.Find
            (a => a.TenderId == ObjectId.Parse("56d55f1d4ee6bc45a0d7b539")).FirstOrDefault();
var modificationsUpdate = Builders<SampleClarification>.Update
    .Set(a => a.RectificationReason, text)
    .Set(v => v.RectificationNumber, 35);
 
if (clar != null)
{
    sc.SampleClarifications.UpdateOne(c => c._id == clar._id, modificationsUpdate);
}

另外,如果您愿意,您可以使其异步。

CRUD 中的另一个 U 或 Upsert(更新插入)

Upsert 意味着以下内容。如果 upsert 选项设置为 true,则如果不存在匹配的文档,则将插入该文档。如果文档存在,则将被替换。

可能有用的代码

SampleDataContext sc = new SampleDataContext();
 
var text = "fasfds afasfas";
var clar =  sc.SampleClarifications.Find
            (a => a.TenderId == ObjectId.Parse("56d55f1d4ee6bc45a0d7b539")).FirstOrDefault();
UpdateOptions options = new UpdateOptions
{
    IsUpsert = true
};
 
if (clar != null)
{
    sc.SampleClarifications.ReplaceOne(c => c._id == clar._id, clar, options);
}

最后删除或 D

最后,您可以 delete 任何文档。这相对容易

SampleDataContext sc = new SampleDataContext();
sc.SampleClarifications.DeleteOne(a => a.RectificationNumber == 10);

投影

假设您不想返回完整的 SampleClarification 字段列表,而是返回它们的子集。为此,您可以使用投影。

想象一下,您不想从 SampleClarification 中提取所有字段,为此,您创建了以下视图类

public class SampleClarificationView : MongoEntityBase
    {
        public ObjectId TenderId { get; set; }
        public int RectificationNumber { get; set; }
    }

然后您可以使用投影

SampleDataContext sc = new SampleDataContext();
var filter = Builders<SampleClarification>.Filter.Empty;
var middle = sc.SampleClarifications.Find(filter).Project(r => new SampleClarificationView()
{
    _id =  r._id,
    TenderId = r.TenderId,
    RectificationNumber = r.RectificationNumber
});
var result = await middle.ToListAsync();

结果将不包含所有字段。

关注点

在本文中,我写下了我对 MongoDB 的 CRUD 操作以及过滤的观察。在编写本文时,我最惊讶的是 MongoDB 的 Projects,它只获取某些字段,而不是所有字段。

历史

  • 2021 年 3 月 3 日:初始发布
© . All rights reserved.