Использование предложения $in для нечувствительного поиска в драйвере mongo db c#

Мне интересно, как использовать нечувствительность к регистру для выражений $in.

Согласно официальному руководству MongoDB вы можете сделать это:

{ name: { $in: [ /^acme/i, /^ack/ ] } }

Я проверил это на Compass, и он работает нормально, поиск нечувствителен.

Мне нужно это с помощью драйвера Mongo на С#.

Я делаю это:

  var array = new BsonArray(companyNames);

  var filter = new BsonDocument { { "Name", new BsonDocument { { "$in", new BsonArray(array) }} } };
  var result = _collection.Find(filter).ToList();

companyNames — это строка[]

Однако это возвращает мне только точные совпадения. Это очевидно, потому что я не включаю выражение «regex». Но я не знаю, как я могу включить регулярное выражение в строку.

Обходной путь — создать выражение $or с регулярным выражением для каждого названия компании.

Кто-нибудь знает, как это сделать?

Спасибо

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
812
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

С mongo-csharp-драйвер вы можете использовать MongoDB.Bson.BsonRegularExpression. Вы можете либо выполнить:

var arrayIn = new BsonArray().Add(
                      new BsonRegularExpression("^acme", "i")
                  ).Add(
                      new BsonRegularExpression("^ack"));
var filter = new BsonDocument { { "name", new BsonDocument { { "$in", arrayIn }} } };
var cursor = collection.Find(filter).ToList();

Или вместо string используйте регулярное выражение и RegexOptions:

var arrayIn = new BsonArray().Add(
                      new BsonRegularExpression(
                          new Regex(
                              "^acme", RegexOptions.IgnoreCase))
                  ).Add(new BsonRegularExpression(
                              "^ack"));

вот элегантное решение с использованием текстового индекса в поле названия компании.

using MongoDB.Entities;

namespace StackOverflow
{
    class Program
    {
        public class Company : Entity
        {
            public string Name { get; set; }
        }

        static void Main(string[] args)
        {
            new DB("test");

            DB.Index<Company>()
              .Key(c => c.Name, KeyType.Text)
              .Option(o => o.Background = false)
              .Create();

            var c1 = new Company { Name = "Ackme" };
            var c2 = new Company { Name = "Acme" };
            var c3 = new Company { Name = "Lackme" };
            var c4 = new Company { Name = "Hackme" };

            c1.Save(); c2.Save(); c3.Save(); c4.Save();

            var names = new[] { "ackme", "acme" };

            var result = DB.SearchText<Company>(string.Join(" ", names));
        }
    }
}

заметьте, в приведенном выше примере используется удобная библиотека MongoDB.Entities. однако концепции те же, но синтаксис официального драйвера громоздкий по сравнению с приведенным выше.

Имейте в виду, что у вас может быть только один текстовый индекс для коллекции. (docs.mongodb.com/manual/core/index-text/…)

Skami 05.06.2019 11:47

Мое решение было перегруженным .In() в качестве метода расширения, принимающим дополнительный параметр для нечувствительности к регистру:

public static class MongoExtensions
{
    public static FilterDefinition<TDocument> In<TDocument>(
        this FilterDefinitionBuilder<TDocument> builder,
        Expression<Func<TDocument, object>> expr,
        IEnumerable<string> values,
        bool ignoreCase)
    {
        if (!ignoreCase)
        {
            return builder.In(expr, values);
        }

        var filters = values
            .Select(v => builder.Regex(expr, new BsonRegularExpression($"^{Regex.Escape(v)}$", "i")));

        return builder.Or(filters);
    }
}

Тогда вы можете просто:

var filter = Builders<Companies>.Filter.In(c => c.Name, companyNames, true);
var result = _collection.Find(filter).ToList();

Другие вопросы по теме