Пользовательский поиск в Dynamics CRM 4.0 - PullRequest
6 голосов
/ 16 января 2009

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

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

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

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

Ответы [ 4 ]

4 голосов
/ 16 января 2009

Поиск и фильтрация с помощью 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();
    }
1 голос
/ 15 апреля 2011

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

1 голос
/ 17 января 2009

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

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

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

0 голосов
/ 28 июля 2010

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

...