2014-11-13 28 views
2

要利用MariaDB 10上的全文索引,我需要在sql字符串中使用這個新的「MATCH AGAINST」語法。我將如何更改Linq-to-Nhibernate爲特定列生成的SQL?

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 to 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 to 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'); 
    

同樣,如果你有更復雜的要求,這也無濟於事。但希望這至少是一個很好的起點。

如果有人想了解如何使這種支持更復雜的情況,這裏是我想你會碰到的問題:

  • 參數從那些AGAINST分離到MATCH
  • 使用NHibernate註冊一個自定義的SQL函數,可以在不同的地方使用任意數量的參數
  • 即使在解決了上述兩個問題之後,也可以創建正確的HQL。
+0

非常感謝。我將在稍後檢查你的教程。 –

+0

此外,更好的主意,只是在linq而不是重寫包含一個新的函數MatchAgainst()。 –

+0

這真的很棒。 NHibernates的可擴展性是... –

相關問題