2014-11-13 1 views
2

Чтобы воспользоваться полной индексацией текста на MariaDB 10, мне нужно использовать этот новый синтаксис «MATCH AGAINST» в строке sql.Как я могу изменить SQL, который Linq-to-Nhibernate генерирует для определенных столбцов?

http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html#function_match

Я думаю, что было бы очень здорово, если бы, только для определенных столбцов, я мог бы переопределить LINQ к NHibernate, чтобы изменить SQL он создает, когда я использую

.Where(x => FullTextIndexedStringProperty.Contains("Some word")).ToList(). 

Кто может дать мне несколько общих указаний о том, как начать?

ответ

3

Это даст вам очень простой пункт MATCH ... AGAINST. Если вы хотите усложниться (больше аргументов, указав модификатор поиска), вам придется внести некоторые большие изменения. Надеюсь, это поможет вам начать работу, хотя:

  1. Создать новый диалект и зарегистрировать простой MATCH (...) AGAINST (...) функции:

    public class CustomMySQLDialect : MySQLDialect 
    { 
        public CustomMySQLDialect() 
        { 
         this.RegisterFunction(
          "matchagainst", 
          new SQLFunctionTemplate(
           NHibernateUtil.Boolean, 
           "match (?1) against (?2)")); 
        } 
    } 
    
  2. Создать статический метод расширения на string, что вы будете использовать в операторах LINQ:

    public static class LinqExtensions 
    { 
        public static bool MatchAgainst(this string source, string against) 
        { 
         throw new NotImplementedException(); 
        } 
    } 
    
  3. Создайте новый LINQ к классу генератора HQL, который связывает метод с функцией SQL мы зарегистрирован в пользовательском диалекта:

    public class MatchAgainstGenerator : BaseHqlGeneratorForMethod 
    { 
        public MatchAgainstGenerator() 
        { 
         this.SupportedMethods = new[] 
         { 
          ReflectionHelper.GetMethod(() => LinqExtensions.MatchAgainst(null, null)) 
         }; 
        } 
    
        public override HqlTreeNode BuildHql(
         MethodInfo method, 
         System.Linq.Expressions.Expression targetObject, 
         ReadOnlyCollection<System.Linq.Expressions.Expression> arguments, 
         HqlTreeBuilder treeBuilder, 
         IHqlExpressionVisitor visitor) 
        { 
    
         return treeBuilder.BooleanMethodCall(
          "matchagainst", 
          arguments.Select(visitor.Visit).Cast<HqlExpression>()); 
        } 
    } 
    
  4. Создание пользовательского LinqToHqlGeneratorsRegistry:

    public class MyLinqToHqlRegistry : DefaultLinqToHqlGeneratorsRegistry 
    { 
        public MyLinqToHqlRegistry() 
        { 
         var generator = new MatchAgainstGenerator(); 
         RegisterGenerator(typeof(LinqExtensions).GetMethod("MatchAgainst"), generator); 
        } 
    } 
    
  5. Используйте свой собственный диалект, и Linq в HQL реестре либо в файле cfg.xml или в коде:

    var cfg = new Configuration() 
        .DataBaseIntegration(db => 
    { 
        db.Dialect<CustomMySQLDialect>(); 
    }) 
    .LinqToHqlGeneratorsRegistry<MyLinqToHqlRegistry>(); 
    
  6. Окончательно, используйте ваш метод расширения в запросе LINQ-to-NHibernate:

    session.Query<Article>() 
        .Where(a => a.Body.MatchAgainst("configured")) 
        .ToList() 
        .Dump(); 
    

    Это будет генерировать SQL, который выглядит следующим образом:

    select 
        userquery_0_.Id as Id51_, 
        userquery_0_.Title as Title51_, 
        userquery_0_.Body as Body51_ 
    from 
        articles userquery_0_ 
    where 
        match (userquery_0_.Body) against ('configured'); 
    

Опять же, это не поможет, если у вас есть более сложные требования. Но, надеюсь, это, по крайней мере, хорошая отправная точка.

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

  • Разделяя аргументы MATCH от тех AGAINST.
  • Регистрация пользовательской функции SQL с NHibernate, которая может принимать произвольное количество аргументов в разных местах
  • Создание правильного языка HQL даже после решения двух вышеперечисленных вопросов.
+0

спасибо. Позднее я просмотрю ваши учебники. –

+0

Кроме того, гораздо лучшая идея просто создать новую функцию MatchAgainst() в linq вместо переопределения. –

+0

Это действительно отличная работа. Расширяемость NHibernates - это ... –

Смежные вопросы