如何忽略我认为基于属性重复的额外结果?
Posted
技术标签:
【中文标题】如何忽略我认为基于属性重复的额外结果?【英文标题】:How to ignore extra results that I consider duplicates based on property? 【发布时间】:2020-06-08 23:06:45 【问题描述】:这可能是一个很长的镜头,但我们开始吧。假设我有以下文档定义:
公共类Test1 公共 ObjectId Id get;set; 公共 int NonUniqueId 获取;放; 公共字符串名称 获取;放; 公共小数价格 得到;放;使用IMongoCollection<Test1>
,我可以过滤结果以记录Name = "somevalue"
,按Price
排序并仅返回10行。
现在到手头的问题。如果过滤器返回了多个文档(带有Name = "somevalue"
)并且NonUniqueId
在该集合中多次出现,我想排除重复的NonUniqueId
并仅返回具有最低Price
的文档。
这个逻辑在代码中很容易实现:获取 10 个结果,如果其中任何一个是“重复的”(即 NonUniqueId
出现多次),保留价格最低的一个并运行另一个搜索,不包括这个NonUniqueId
。但是,它需要多个数据库调用,这不是很好(最坏的情况下最多 10 个)。
在 MongoDB(使用 C# 驱动程序)中,有没有办法根据属性忽略这些“重复”结果,理想情况下,只返回另一个属性的最小值(或任何具有相同效果的东西)?
【问题讨论】:
【参考方案1】:试试这个管道:
db.Product.aggregate([
$match: Name: "book"
,
$sort: Price: 1
,
$group:
_id: "$NonUniqueId",
product: $first: "$$ROOT"
,
$replaceWith: "$product"
])
https://mongoplayground.net/p/sqSjiXQhdlF
更新:添加了c#
由于需要投影,c#版本有点不方便:
var result = collection.AsQueryable()
.Where(p => p.Name == "book")
.OrderBy(p => p.Price)
.GroupBy(p => p.NonUniqueId)
.Select(g => new Product
Id = g.First().Id,
Name = g.First().Name,
NonUniqueId = g.First().NonUniqueId,
Price = g.First().Price
)
.ToList();
测试程序:
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using MongoDB.Entities;
using MongoDB.Entities.Core;
using System.Linq;
namespace ***
public class Product : Entity
public int NonUniqueId get; set;
public string Name get; set;
public decimal Price get; set;
public static class Program
private static void Main()
new DB("test");
var result = DB.Queryable<Product>()
.Where(p => p.Name == "book")
.OrderBy(p => p.Price)
.GroupBy(p => p.NonUniqueId)
.Select(g => new Product
ID = g.First().ID,
Name = g.First().Name,
NonUniqueId = g.First().NonUniqueId,
Price = g.First().Price
)
.ToList();
【讨论】:
是的...投影将是这里的问题。该集合已获得 100000 份文档。我并不特别喜欢下载所有这些,但您可以从驱动程序运行原始查询。极限射门会绕组吗? @Dawid 您可以毫无问题地进行限制。限制是施加在光标 afaik 上的。 @DawidO 认为您可能对使用 c# 运行原始查询的更好方法感兴趣。看看我写的this library。 也许我在这里遗漏了一些明显的东西,我不能这样做collection.AsQueryable()
因为我不想在我的本地机器上下载整个集合。关于库,您能否提供更多详细信息如何将其与我提供的代码示例集成?
@DawidO 给你:gist.github.com/dj-nitehawk/bda542ca93609fe12a670ccab89dc1d2【参考方案2】:
尝试Distinct
方法,如this答案所示。您甚至可以定义一个自定义的Equals
函数(通过定义一个实现IEqualityComparer
的类)来执行您需要执行的检查
【讨论】:
我不需要比较 C# 对象。我希望 Mongo 为我完成繁重的工作。以上是关于如何忽略我认为基于属性重复的额外结果?的主要内容,如果未能解决你的问题,请参考以下文章
基于对象属性对数组进行排序 - Javascript [重复]