Как фильтровать массив объектов, равный имени и содержащий значение?

В моей базе данных mongodb есть массив объектов, который выглядит примерно так.

[
 {
  _id: 123,
  info: [
         {
           name: John,
           random: ['31', 'food', 'sleep']
         }
        ]
 },
 {
  _id: 234,
  info: [
         {
           name: Amy,
           random: ['tv', 'food', 'sleep']
         }
        ]
 },
 {
  _id: 345,
  info: [
         {
           name: John,
           random: ['cars', 'tv31', 'sleep']
         }
        ]
 },
]

В С#, как мне фильтровать информацию, где имя Джон, а случайное число содержит 31? Я также не знаю, в чем разница между AnyIn и In.

🤔 А знаете ли вы, что...
C# активно развивается и обновляется, с появлением новых версий и функциональности.


67
3

Ответы:

в С#, как мне фильтровать информацию, где имя "John" и случайное значение "31"?

У вас должна быть возможность запросить свойство info каждого элемента данных, чтобы отфильтровать результаты, например:

var results = data.Where(item => 
    item.info.Any(info => 
        info.name == "John" && 
        info.random.Any(random => random == "31")));

Следующий код работает.

    public class Item
    {
        [BsonId]  
        [BsonRepresentation(BsonType.Int32)] 
        public int Id { get; set; }
        public IEnumerable<Person> info { get; set; }   
    }

    public class Person
    {
        public string name { get; set; }
        public List<string> random { get;set; }

    }
var filter = Builders<Item>.Filter.Where(item => item.info.Any(info => (info.random.Any(random => random.Contains("31"))) && (info.name == "John")));
var results = collection1.Find(filter).ToList();
var results = collection1.AsQueryable()
                                .Where(item => item.info.Any(info => (info.random.Any(random => random.Contains("31"))) && (info.name == "John")))
                                .ToList();

Решено

Запрос LINQ (который рассматривается другими ответчиками) работает и проще для тех, кто не знаком с запросом MongoDB Fluent.


Для тех, кто ищет синтаксис MongoDB Fluent:

Предположим, что ваши классы моделей такие, как показано ниже:

public class RootModel
{
   [BsonId]
   public int Id { get; set; }

   public InfoModel[] Info { get; set; }
}

[BsonNoId]
public class InfoModel
{
    public string Name { get; set; }

    public string[] Random { get; set; }
}

Вам следует работать с .ElemMatch и .AnyIn:

var filter = Builders<RootModel>.Filter.ElemMatch(x => x.Info,
        Builders<InfoModel>.Filter.Eq(y => y.Name, "John")
        & Builders<InfoModel>.Filter.AnyIn(y => y.Random, new string[] { "31" }));

На вопрос владельца сообщения о различиях между .In и .AnyIn:

In работает, когда ваше поле представляет собой одно значение и используется для сопоставления любого элемента из предоставленного входного массива.

AnyIn работает, когда ваше поле представляет собой массив и используется для сопоставления любого элемента из предоставленного входного массива.


В зависимости от вашего сценария вы получите синтаксическую ошибку при использовании .In для реализации In, как показано ниже:

public FilterDefinition<TDocument> In<TField>(Expression<Func<TDocument, TField>> field, IEnumerable<TField> values)
{
    return In(new ExpressionFieldDefinition<TDocument, TField>(field), values);
}

Если только вы не проверяете весь массив Random, который точно соответствует массиву, например:

random: {
   $in: [['31', 'food', 'sleep'], ...]
}

Итак, это работает с In:

Builders<InfoModel>.Filter.In(y => y.Random, 
    new string[][] { new string[] { "31", "food", "sleep" } })

Это другая история сопоставления точного значения массива по сравнению с текущим вопросом, который требует сопоставления любого элемента массива.