6

関連する 2 つの質問があります。

1 つ目: Dynamics CRM 4.0 のカスタム エンティティに対して全文検索を実行しようとしています。誰かがこれを以前にやったことがありますか、それを行う方法を知っていますか?

Web サービスと SDK を使用して QueryExpressions を構築できることはわかっていますが、この方法を使用してブール型の構文で全文検索を行うことはできますか? 私が知る限り、それはうまくいきません。

2 番目: Dynamics CRM 4.0 で提供される検索機能に限界を感じている人はいますか? サードパーティの検索製品がいくつかあることは知っていますが、気に入った製品はまだ見つかりません。任意の提案をいただければ幸いです。

4

4 に答える 4

4

CRM SDKを介した検索とフィルタリングには、慣れるまでに時間がかかります。全文検索をシミュレートするには、ネストされたFilterExpressionsをQueryExpression.Criteriaとして使用する必要があります。 ネストされたフィルターのSDKページ 最も難しい部分は、親子関係を構築する方法を理解することです。非常に多くのブール論理が進行しているため、迷子になりがちです。

カスタムエンティティの1つに「検索エンジン」を構築する必要がありました。複数の検索可能な属性を持つ複雑な検索文字列(「1つと2つまたは3つ」)にこのメソッドを使用するのは醜いものでした。興味があれば、掘り下げることができます。実際にはサポートされていませんが、データベースに直接アクセスできる場合は、SQLの全文検索機能を使用することをお勧めします。

-わかりました、どうぞ。これをコピーして貼り付けて、ニーズを満たすことはできないと思います。私の顧客はキーワード検索を2〜3回しか行っておらず、この結果に満足していました。単純な検索シナリオでこれを行うのがどれほど苦痛であるかがわかります。私は基本的に、「動作する」までコードを取り出しました。

    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

2 つ目 - すべてのカスタム エンティティと属性、および Out of Box エンティティと属性を検索する機能を提供する、Akvelon による「グローバル検索」をお勧めします。また、添付書類の内容を検索するためにFTSを使用しています。詳細については、公式サイトをご覧ください: http://www.akvelon.com/Products/Dynamics%20CRM%20global%20Search/default.aspx

于 2011-04-15T05:30:07.357 に答える
1

うーん、なかなか面白いシナリオだ…

確かに「Like」クエリを実行し、検索に含めたい列/属性条件を「or」することができます。これは、CRM がエンティティ リストの上のボックスからクエリを実行する方法のようです (そして、それらは非常に高速です)。CRM データベースにはフルテキスト インデックスがあるように見えますが、どの列を使用してデータを入力するのか正確にはわかりません。

そして、CRM クエリが大好きな場合はLinqtoCRMを思い出してください (私はプロジェクトを開始しました。恥知らずなプラグインで申し訳ありません)。

于 2009-01-17T20:49:27.170 に答える
0

データベースで提供されている Dynamics CRM フィルター ビューを利用することをお勧めします。次に、ネイティブ SQL のすべての機能を利用して、必要な LIKE やその他のロジックを実行できます。さらに、フィルタリングされたビューはセキュリティでトリミングされているため、権限のないユーザーがレコードにアクセスすることを心配する必要はありません。

于 2010-07-28T03:13:46.283 に答える