В моей базе данных 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.
data.Where(x => x.info.Any(y => y.name == "John" && y.random.Any(z => z == "31")));
должно помочь. Или, если вы имели в виду, что случайные строки содержат 31, то data.Where(x => x.info.Any(y => y.name == "John" && y.random.Any(z => z.Contains("31"))));
должно работать.
Всегда ли поле info
представляет собой массив с одним объектом, как показано (если да, то почему это массив)?
@user20042973 user20042973 эй, нет, это не всегда один объект, но я не думал, что мне нужно добавить больше объектов для этого вопроса.
я ищу, где имя равно Джону, а любая строка в случайном порядке содержит 31
спасибо @SaniHuttunen
в С#, как мне фильтровать информацию, где имя
"John"
и случайное значение"31"
?
У вас должна быть возможность запросить свойство info
каждого элемента данных, чтобы отфильтровать результаты, например:
var results = data.Where(item =>
item.info.Any(info =>
info.name == "John" &&
info.random.Any(random => random == "31")));
Имейте в виду, что OP может означать случайные строки, содержащие 31. Тогда это должно включать объект с _id = 345
, поскольку tv31
содержит 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" } })
Это другая история сопоставления точного значения массива по сравнению с текущим вопросом, который требует сопоставления любого элемента массива.
Когда вы говорите «содержит» 31, вы имеете в виду, что строка содержит подстроку 31 или там, где она содержит именно «31»? Первый не будет эффективным запросом Mongo, если у вас нет текстового индекса на
info.random
(и, возможно, даже тогда — я особо не использовал текстовые индексы Mongo).