Вопрос

У меня есть два связанных вопроса.

Первый:Я хочу выполнить полнотекстовый поиск по пользовательскому объекту в Dynamics CRM 4.0.Кто-нибудь делал это раньше или знает, как это сделать?

Я знаю, что я могу создавать выражения запросов с помощью веб-сервиса и sdk, но могу ли я выполнить полнотекстовый поиск с синтаксисом логического типа, используя этот метод?Насколько я могу судить, это не сработает.

Второй:Кто-нибудь еще чувствует себя ограниченным в возможностях поиска, предоставляемых Dynamics CRM 4.0?Я знаю, что есть несколько поисковых продуктов 3rd pary, но я пока не нашел ни одного, который бы мне понравился.Будем признательны за любые предложения.

Это было полезно?

Решение

Поиск и фильтрация с помощью CRM SDK действительно требуют некоторого времени, чтобы привыкнуть.Чтобы имитировать полнотекстовый поиск, вам необходимо использовать вложенные выражения Filter в качестве выражения QueryExpression.Критерии. Страница 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();
    }

Другие советы

Хм, это довольно интересный сценарий...

Вы, конечно, могли бы выполнить запрос "Нравится" и "или" вместе с условиями столбцов / атрибутов, которые вы хотите включить в поиск.Похоже, именно так CRM выполняет запросы из списка объектов в поле выше (и они выполняются достаточно быстро).Похоже, что база данных CRM имеет полнотекстовый индекс, хотя после краткого ознакомления мне немного неясно, какие именно столбцы используются для его заполнения.

И помни LinqtoCRM для CRM запрос love (я запустил проект, извините за бесстыдную вставку).

Во-вторых, я могу порекомендовать "Глобальный поиск" от Akvelon, который предоставляет возможность поиска по всем пользовательским объектам и атрибутам, а также по готовым объектам и атрибутам.Также они используют FTS для поиска по содержимому прикрепленных документов.Вы можете найти более подробную информацию на их официальном сайте: http://www.akvelon.com/Products/Dynamics%20CRM%20global%20Search/default.aspx

Я бы предложил использовать отфильтрованные представления Dynamics CRM, предоставленные для вас в базе данных.Затем вы можете использовать всю мощь собственного SQL для выполнения любой подобной или другой необходимой вам логики.Кроме того, отфильтрованные представления защищены системой безопасности, так что вам не придется беспокоиться о том, что пользователи получат доступ к записям, на которые у них нет разрешения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top