【问题标题】:Write ICriteria for CONTAINSTABLE (sql fulltext search)为 CONTAINSTABLE 编写 ICriteria(sql 全文搜索)
【发布时间】:2011-12-23 18:30:36
【问题描述】:

我需要对多个表进行全文搜索,所以我使用 SqlServer CONTAINSTABLE 函数,它可以作为 SQL 查询正常工作,但是我如何将 CONTAINSTABLE 重写为 NHibernate ICriteria。

SELECT DISTINCT CP.* FROM ContentPack CP
    INNER JOIN [Content] C ON CP.ContentPackId = C.ContentPackId

 INNER JOIN
     CONTAINSTABLE([Content], (Title, [Description]), 'Foo*') AS KEY_TBL
     ON C.Title = KEY_TBL.[KEY]

我需要将此 SQL 转换为 NHibernate Criteria,有人可以帮助我吗?

【问题讨论】:

    标签: sql-server nhibernate fluent-nhibernate full-text-search criteria


    【解决方案1】:

    我也遇到了同样的问题

    NHibernate + SqlServer full text search

    我没有找到任何解决方案,所以我选择了拦截器概念

    1)我为主表创建了分离条件并加入了全文表

    2)还为nhibernate创建了一个自定义拦截器,它将用(select [key] as foreignkey,[rank] as rank FROM CONTAINSTABLE(full_text,full_text_col , 'Foo*'))替换全文表名

    代码

    生成的查询

    SELECT c.id,
            c.name,
            ft.id, 
            ft.rank 
    FROM candidates c 
        INNER JOIN full_text ft ON ft.id  = c.fulltext_id 
    ORDER BY rank
    

    拦截后查询

    SELECT c.id,
            c.name,
            ft.id,
            ft.rank 
    FROM candidates c 
        INNER JOIN (
                SELECT [KEY] AS id ,[rank] AS rank 
                FROM CONTAINSTABLE(full_text, full_text_col, 'Foo*')
                   ) AS ft ON ft.id  = c.fulltext_id 
    ORDER BY rank
    

    ****分离标准 ****

            DetachedCriteria candidateCriteria = DetachedCriteria.For<Candidate>();
            DetachedCriteria fullTextCriteria = candidateCriteria.CreateCriteria("FullText");  
    

    拦截器代码

    public interface CustomInterceptor : IInterceptor, EmptyInterceptor
    {
        private string fulltextString;
        public string FulltextString
        {
            get { return fulltextString; }
            set { fulltextString = value; }
        }
        SqlString IInterceptor.OnPrepareStatement(SqlString sql)
        {
            string query = sql.ToString();
            if (query.Contains("full_text"))
            {
                sql = sql.Replace("full_text", "(select [key] as foreignkey,[rank] as Rank FROM CONTAINSTABLE(full_text, full_text_col, '"+FulltextString+"')) AS ft'");
            }
            return sql;
        }
    }
    

    实体

    候选人表

    id 整数

    名称字符串

    fulltext_id

    full_text 表包含全文索引

    id 整数

    full_text_col 文本

    rank int //总是为空

    关系

    候选人 - 全文 (1-1)

    OpenSession

    CustomInterceptor custonInterceptor=new CustomInterceptor();
    custonInterceptor.FulltextString="YourString";
    sessionFactory.OpenSession(custonInterceptor);
    

    【讨论】:

    • @chuck-查看已编辑的代码-目前我没有确切的代码(在办公室),无论如何这种方法是一个精确的解决方案,它是一个 hack
    • 我有很多表,我使用全文搜索,有时我一次搜索多个表(加入),我应该为每个我必须搜索的表做一个虚拟表/拦截器吗?
    • 不,您必须只使用一个虚拟表来获取全文结果返回值。即(full_text id int key int)该表始终不包含任何值并添加具有Id和Key属性的实体FullText跨度>
    • 这个虚拟表必须对我搜索的每个表都有一个外键(我看到你有“candidate_Id”)?
    • @ChuckNorris-在这里我分享了包含实际 nhibernate 生成查询和由拦截器编辑的查询的查询的文档。我认为通过查看此查询您可能会有所了解。我还为两个表指定了架构(主表将连接到多个表和全文表,我在其中配置了全文索引)。有了这个,你可以一次搜索多个表(加入)bcoz我在做同样的事情。检查链接box.com/s/7if894sr9piz41go7ctz
    【解决方案2】:

    您可以使用命名查询

    http://nhibernate.info/blog/2009/04/16/nhibernate-mapping-named-queries-lt-query-gt-and-lt-sql-query-gt.html

    <sql-query name="MyQuery">
        <return alias="cp"
                        class="ContentPack"/>
        SELECT DISTINCT {cp.*}
        INNER JOIN [Content] C ON CP.ContentPackId = C.ContentPackId
        INNER JOIN
         CONTAINSTABLE([Content], (Title, [Description]), 'Foo*') AS KEY_TBL
         ON C.Title = KEY_TBL.[KEY]
    </sql-query>
    

    【讨论】:

    • 我需要使用 ICriteria 而不是 SQL
    • 标准 API 仅允许您在联接中使用实体。您不能将表值函数指定为实体的源。因此,它不受支持。您可以使用拦截器尝试其他解决方案,但它不太可能非常稳定 imo。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-16
    • 1970-01-01
    • 1970-01-01
    • 2013-06-07
    • 1970-01-01
    • 2010-09-06
    相关资源
    最近更新 更多