0

I am using Sitecore 10 and trying to implement keyword search with xConnect contact. I want to search for contacts that have email or phone number that contains the inputted keyword. Below is my approach.

var expandOptions = new ContactExpandOptions(EmailAddressList.DefaultFacetKey, ListSubscriptions.DefaultFacetKey, PersonalInformation.DefaultFacetKey, PhoneNumberList.DefaultFacetKey);

                IAsyncQueryable<Sitecore.XConnect.Contact> queryable;

                if (!string.IsNullOrWhiteSpace(searchTerm))
                {
                    queryable = client.Contacts.WithExpandOptions(expandOptions).Where(c => c.GetFacet<PhoneNumberList>(CollectionModel.FacetKeys.PhoneNumberList).PreferredPhoneNumber.Number.Contains(searchTerm) || c.GetFacet<EmailAddressList>(CollectionModel.FacetKeys.EmailAddressList).PreferredEmail.SmtpAddress.Contains(searchTerm))
                        .Skip((page - 1) * pageSize)
                        .Take(pageSize);
                }

The problem is when this function is executed, it throws the exception: YourLinqIsTooStrongException

Turn out the xConnect search does not implement all of IAsyncQueryable methods and Contains() method is not supported as mentioned in this official document: https://doc.sitecore.com/xp/en/developers/92/sitecore-experience-platform/supported-methods-and-operators-for-xconnect-search.html

I've enabled indexing of PII sensitive data.

Has anybody encountered this error before and do you know how to resolve it?

1 Answer 1

1

xConnect Search does not support Contains extension method as you rightly identified, you may fetch the contacts in batches using GetBatchEnumerator and iterate through contacts until you find the match for the Keyword (avoid skip as skipping large results proves to be inefficient as per documentation).

Sample code with GetBatchEnumerator: (you may edit batch size depending on your contact capacity)

           if (string.IsNullOrWhiteSpace(searchTerm))
            {
                return null;
            }

            var batch = await client.Contacts.WithExpandOptions(expandOptions)
                .GetBatchEnumerator();

            List<Contact> matchedContacts = new List<Contact>();

            try
            {
                while (await batch.MoveNext(200,
                    token))
                {
                    var contacts = batch.Current;
                    foreach (var contact in contacts)
                    {
                        var preferredPhoneNumber = contact.GetFacet<PhoneNumberList>(Sitecore.XConnect.Collection.Model.CollectionModel.FacetKeys.PhoneNumberList).PreferredPhoneNumber.Number;
                        var preferredEmail = contact.GetFacet<EmailAddressList>(Sitecore.XConnect.Collection.Model.CollectionModel.FacetKeys.EmailAddressList).PreferredEmail.SmtpAddress;
                        if(preferredPhoneNumber.Contains(searchTerm) || preferredEmail.Contains(searchTerm))
                        {
                            matchedContacts.Add(contact);//Optimize: you may return on first match unless you want to gather all contacts.
                        }
                    }

                    if (token.IsCancellationRequested)
                    {
                        break;
                    }
                }
            }
            catch (OperationCanceledException)
            {
            }

TIP: In order to further curate the contacts before the keyword filter ensure to use any other conditions(using Where) which may help bring down the batch size.(Ex TimeSpan, Recent interactions etc. based on your requirements)

Hope it helps !!

1
  • Thanks for your answer. I've used GetBatchEnumerator as your suggestion and it worked. Commented Mar 11, 2022 at 8:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.