c# - 判断一组 id 中的哪些 id 仍在数据库中的有效方法(即,将输入 id 与集合 id 相交)MongoDb C#
问题描述
我有一个包含大约 8000 万份文档的集合。通过 API,用户可以验证数据库中是否仍然存在一组 id(输入集)。输入集可能相当大,但我会将验证分成大约几块。10000 个 ID。基本上我想得到数据库ID和输入集之间的交集。
我想用 Linq 做到这一点,但欢迎提出其他建议。
下面是一些示例代码,显示了我的场景以及我到目前为止所尝试的内容。
第一种方法是我会做的,但它会抛出 NotSupportedException :表达式树中不支持方法 Intersect :
第二种方法有效,但在大型集上确实很慢。
第三种方法比第二种方法快,但是我必须在内存中加载 8000 万个 id。
我们试图坚持使用 C# 包装器提供的 linq 接口,但有时这很困难。任何指针表示赞赏。我想有一种方法可以通过 $setIntersection 使用不同的构建器和管道定义,但我无法理解关于此的 c# 文档。
private string[] FilterOnExistInDatabase1(string[] candidates)
{
// Query<T> is just a wrapper to the collection and returns a IQueryable<T>
return mongoRepository.Query<TestModel>().Select(x => x.Id).Intersect(candidates).ToArray();
}
private string[] FilterOnExistInDatabase2(string[] candidates)
{
// Query<T> is just a wrapper to the collection and returns a IQueryable<T>
return mongoRepository.Query<TestModel>().Select(x => x.Id).Where(x => candidates.Contains(x)).ToArray();
}
private string[] FilterOnExistInDatabase3(string[] candidates)
{
// Query<T> is just a wrapper to the collection and returns a IQueryable<T>
var allExistingIds = mongoRepository.Query<TestModel>().Select(x => x.Id).ToArray();
var existingCandidates = allExistingIds.Intersect(candidates).ToArray();
return existingCandidates;
}
[Test]
public void SampleQuery()
{
var models = Enumerable.Range(0, 10).Select(x => new TestModel()).ToArray();
mongoRepository.InsertMany(models, CancellationToken.None);
var deletedId = "I no longer exist";
var candidates = models.Select(x => x.Id).Concat(new []{deletedId}).ToArray();
var existingCandidates = FilterOnExistInDatabase3(candidates);
Assert.That(existingCandidates.Length, Is.EqualTo(models.Length));
Assert.False(existingCandidates.Contains(deletedId));
Assert.That(existingCandidates.Length, Is.EqualTo(candidates.Length - 1));
}
解决方案
下面的方法怎么样?基本上,您会取回数据库中存在的 ID 数组,并使用 linq 在客户端生成交集以获取无效/已删除的 ID。
using MongoDB.Bson;
using MongoDB.Entities;
using MongoDB.Entities.Core;
using System;
using System.Linq;
namespace StackOverflow
{
public class Item : Entity
{
public string Name { get; set; }
}
public class Program
{
private static void Main(string[] args)
{
new DB("test", "localhost");
var one = new Item { Name = "one" }; one.Save();
var two = new Item { Name = "two" }; two.Save();
var thr = new Item { Name = "three" }; thr.Save();
var inputIDs = new[] { one.ID, two.ID, ObjectId.GenerateNewId().ToString() };
var validIDs = DB.Queryable<Item>() // for official driver use: collection.AsQueryable()
.Where(i => inputIDs.Contains(i.ID))
.Select(i => i.ID)
.ToArray();
var deletedIDs = inputIDs.Except(validIDs).ToArray();
}
}
}
从理论上讲,这应该比上面的第二种方法更快,因为它不会导致集合中每个 ID 的投影。如果您可以接受这种方法,我很想知道 mongodb 完成 8000 万个文档的任务需要多少毫秒。
推荐阅读
- api - 如何在 Kong 中进行 API 监控,例如查看使用次数/响应代码/消费模式等?
- javascript - 使用 ajax 从烧瓶到 javascript 的图像
- mysql - 超过锁定等待超时;尝试重新启动事务 - 插入语句
- python - 我在为 python 使用 beautifulsoup 包时遇到了麻烦
- javascript - 为什么我的 JSON 响应在另一个函数中无法识别?
- javascript - 基于条件的动态行选择
- swift - Swift枚举,从关联的枚举中获取原始值
- java - 静态块和静态内存初始化和实现
- vb.net-2010 - 如何使用 do while 循环获得两种产品的奖品
- php - 如果在数据库中找到卡号,是否进行交易?