Как игнорировать дополнительные результаты, которые я считаю дубликатами на основе свойства? - PullRequest
1 голос
/ 25 февраля 2020

Это может быть длинный выстрел, но здесь мы go. Предположим, у меня есть следующее определение документа:

public class Test1 {
    public ObjectId Id {get;set;}
    public int NonUniqueId { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

Используя IMongoCollection<Test1>, я могу отфильтровать результаты по документам, в которых Name = "somevalue", отсортировать по Price и вернуть только 10 строк.

var builder = Builders.Filters;
var filter = builder.Where(x=>x.Name == "somevalue");

var result = await collection.Find(filter).SortBy(x=>x.Price).Limit(10).ToListAsync();

Теперь к вопросу. Если фильтр возвращает более одного документа (с Name = "somevalue") и NonUniqueId встречается более одного раза в этом наборе, я хотел бы исключить дубликаты NonUniqueId и вернуть только тот, который имеет наименьшее значение Price.

Эту логику c довольно легко реализовать в коде: получить 10 результатов, если какой-либо из них является «дубликатом» (т. Е. NonUniqueId встречается более одного раза), сохранить тот, который имеет наименьшую цену и запустите другой поиск, исключая этот NonUniqueId. Однако для этого требуется несколько вызовов БД, что не очень хорошо (до 10 в худшем случае).

В MongoDB (с драйвером C#) есть способ игнорировать эти «дублирующие» результаты, основанные на свойство и, в идеале, вернуть только минимальное значение другого свойства (или что-либо с таким же эффектом)?

Ответы [ 2 ]

1 голос
/ 25 февраля 2020

дать этому конвейеру попытку:

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 StackOverFlow
{
    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();
        }
    }
}
0 голосов
/ 25 февраля 2020

Попробуйте метод Distinct, как показано в этом ответе. Вы даже можете определить пользовательскую функцию Equals (определив класс, реализующий IEqualityComparer), который выполняет проверки, необходимые для выполнения

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...