6

我有两个相关的问题。

首先:我希望针对 Dynamics CRM 4.0 中的自定义实体进行全文搜索。有没有人这样做过或知道怎么做?

我知道我可以使用 Web 服务和 sdk 构建 QueryExpressions,但是我可以使用这种方法使用布尔类型语法进行全文搜索吗?据我所知,这不会奏效。

第二:其他人是否觉得 Dynamics CRM 4.0 提供的搜索能力有限?我知道那里有一些 3rd parry 搜索产品,但我还没有找到我喜欢的。任何建议,将不胜感激。

4

4 回答 4

4

通过 CRM SDK 进行搜索和过滤确实需要一些时间来适应。为了模拟全文搜索,您需要使用嵌套的 FilterExpressions 作为您的 QueryExpression.Criteria。 嵌套过滤器 的 SDK 页面 最难的部分是弄清楚如何建立父子关系。有太多布尔逻辑,很容易迷路。

我需要为我们的一个自定义实体构建一个“搜索引擎”。将这种方法用于具有多个可搜索属性的复杂搜索字符串(“一和二或三”)很难看。如果你有兴趣,我可以挖掘它。虽然它并不真正受支持,但如果您可以直接访问数据库,我建议使用 SQL 的全文搜索功能。

——好的,给你。我认为您无法复制粘贴此内容并满足您的需求。我的客户只进行了两到三个关键词搜索,他们对此结果感到满意。您可以看到在一个简单的搜索场景中这样做是多么痛苦。我基本上吐出代码,直到它“工作”。

    private FilterExpression BuildFilterV2(string[] words, string[] seachAttributes)
    {
        FilterExpression filter = new FilterExpression();
        List<FilterExpression> allchildfilters = new List<FilterExpression>();

        List<string> andbucket = new List<string>();
        List<string> orBucket = new List<string>();

        // clean up commas, quotes, etc
        words = ScrubWords(words);

        int index = 0;

        while (index < words.Length)
        {
            // if current word is 'and' then add the next wrod to the ad bucket
            if (words[index].ToLower() == "and")
            {
                andbucket.Add(words[index + 1]);
                index += 2;
            }
            else
            {
                if (andbucket.Count > 0)
                {

                    List<FilterExpression> filters = new List<FilterExpression>();
                    foreach (string s in andbucket)
                    {
                        filters.Add(BuildSingleWordFilter(s, seachAttributes));
                    }

                    // send existing and bucket to condition builder 
                    FilterExpression childFilter = new FilterExpression();
                    childFilter.FilterOperator = LogicalOperator.And;
                    childFilter.Filters = filters.ToArray();

                    // add to child filter list
                    allchildfilters.Add(childFilter);

                    //new 'and' bucket
                    andbucket = new List<string>();
                }
                if (index + 1 < words.Length && words[index + 1].ToLower() == "and")
                {
                    andbucket.Add(words[index]);
                    if (index + 2 <= words.Length)
                    {
                        andbucket.Add(words[index + 2]);
                    }
                    index += 3;
                }
                else
                {
                    orBucket.Add(words[index]);
                    index++;
                }
            }
        }

        if (andbucket.Count > 0)
        {
            List<FilterExpression> filters = new List<FilterExpression>();
            foreach (string s in andbucket)
            {
                filters.Add(BuildSingleWordFilter(s, seachAttributes));
            }

            // send existing and bucket to condition builder 
            FilterExpression childFilter = new FilterExpression();
            childFilter.FilterOperator = LogicalOperator.And;
            childFilter.Filters = filters.ToArray();

            // add to child filter list
            allchildfilters.Add(childFilter);

            //new 'and' bucket
            andbucket = new List<string>();
        }
        if (orBucket.Count > 0)
        {
            filter.Conditions = BuildConditions(orBucket.ToArray(), seachAttributes);
        }
        filter.FilterOperator = LogicalOperator.Or;
        filter.Filters = allchildfilters.ToArray();

        return filter;
    }
    private FilterExpression BuildSingleWordFilter(string word, string[] seachAttributes)
    {
        List<ConditionExpression> conditions = new List<ConditionExpression>();

        foreach (string attr in seachAttributes)
        {
                ConditionExpression expr = new ConditionExpression();
                expr.AttributeName = attr;
                expr.Operator = ConditionOperator.Like;
                expr.Values = new string[] { "%" + word + "%" };

                conditions.Add(expr);
        }

        FilterExpression filter = new FilterExpression();
        filter.FilterOperator = LogicalOperator.Or;
        filter.Conditions = conditions.ToArray();

        return filter;
    }

    private ConditionExpression[] BuildConditions(string[] words, string[] seachAttributes)
    {
        List<ConditionExpression> conditions = new List<ConditionExpression>();

        foreach (string s in words)
        {
            foreach (string attr in seachAttributes)
            {
                ConditionExpression expr = new ConditionExpression();
                expr.AttributeName = attr;
                expr.Operator = ConditionOperator.Like;
                expr.Values = new string[] { "%" + s + "%" };

                conditions.Add(expr);
            }
        }

        return conditions.ToArray();
    }
于 2009-01-16T18:04:30.140 回答
1

嗯,这是一个非常有趣的场景......

您当然可以执行“喜欢”查询,并将您希望包含在搜索中的列/属性条件一起“或”。这似乎是 CRM 从实体列表上方的框中进行查询的方式(而且速度非常快)。看起来 CRM 数据库有一个全文索引,虽然在简短的浏览之后,究竟使用了哪些列来填充它对我来说有点模糊。

并记住LinqtoCRM对 CRM 查询的热爱(我开始了这个项目,对于无耻的插件感到抱歉)。

于 2009-01-17T20:49:27.170 回答
1

其次 - 我可以推荐 Akvelon 的“全局搜索”,它提供了搜索所有自定义实体和属性以及开箱即用实体和属性的能力。他们还使用 FTS 在附加文档内容中进行搜索。您可以在他们的官方网站上找到更多详细信息:http ://www.akvelon.com/Products/Dynamics%20CRM%20global%20Search/default.aspx

于 2011-04-15T05:30:07.357 回答
0

我建议使用数据库中为您提供的 Dynamics CRM 过滤视图。然后,您可以利用本机 SQL 的所有功能来执行您需要的任何 LIKE 或其他逻辑。此外,过滤后的视图经过安全调整,因此您不必担心用户访问他们无权访问的记录。

于 2010-07-28T03:13:46.283 回答