Supported methods and operators for xConnect search

Abstract

An overview of supported and unsupported methods and operators when using the xConnect Client API to search contacts and interactions.

xConnect search does not implement all of IAsyncQueryable<T> methods and throws a Sitecore.XConnect.Search.YourLinqIsTooStrongException or an XdbModelException exception if you try to use a method that is not supported. The following table applies to both contact and interaction searches unless explicitly stated.

Refer to the xConnect Client API for an overview of synchronous and asynchronous extension methods.

Extension method and operator support matrix:

Method/Operator

xConnect

IAsyncQueryable<T>

Notes

.Where()

Yes

Yes

.Any()

Yes

Yes

See the Azure Search list field limitations section for restrictions.

.ToArray()

Yes

Yes

.ToList()

Yes

Yes

.Count()

Yes

Yes

.OrderBy()

Yes

Yes

.OrderByDescending()

Yes

Yes

.ThenBy()

Yes

Yes

.ThenByDescending()

Yes

Yes

.Skip()

Yes

Yes

See Paginating xConnect search results.

.Take()

Yes

Yes

See Paginating xConnect search results.

.FirstOrDefault()

Yes

Yes

.First()

Yes

Yes

.Single()

Yes

Yes

.SingleOrDefault()

Yes

Yes

== and !=

Yes

Yes

< and >

Yes

Yes

<= and >=

Yes

Yes

&& and ||

Yes

Yes

.GetBatchEnumerator()

Yes

No

.GetBatchEnumeratorSync()

Yes

No

.ToSearchResults()

Yes

No

.WithExpandOptions()

Yes

No

.AsEnumerable()

Yes

No

Synchronous only.

Contains

No

Yes

StartsWith

No

Yes

EndsWith

No

Yes

ToString

No

Yes

Equals

No

Yes

Note

There is no Like() extension method.

xConnect search provider limitations

xConnect search providers do not support the following scenarios:

Limitations of xConnect search providers:

Scenario

Limitation

Custom methods inside search expressions

The xConnect Client API does not support custom method calls inside LINQ query expressions. You receive a Sitecore.XConnect.Search.YourLinqIsTooStrongException or an XdbModelException exception.

Search for null values

It is not possible to check if a facet is null. For example:

var notWebVisits = client.Interactions.Where(c => c.WebVisit() == null);

Search by Timespan in custom event properties

The following query (using a custom Timespan property) is unsupported:

var interactions = await _client.Contacts.Where(c => c.Interactions.Any(i => i.Events.OfType<CampaignEvent>().Any(e => e.CustomCampaignTimespan == TimeSpan.Zero)));

Note

You can still use the default Duration property on events. This restriction only applies to events, not facets.

First, FirstOrDefault, Last, LastOrDefault, or Count inside a LINQ expression

Not supported:

// First() inside a LINQ expression is unsupported:
var interactions = await _client.Interactions.Where(i => i.Events.First().EngagementValue == 11).ToList();

// FirstOrDefault() inside a LINQ expression is unsupported:
var contacts = await _client.Contacts.Where(contact => contact.Interactions.OrderByDescending(x => x.StartDateTime).FirstOrDefault().WebVisit().SiteName == "value");

// Last() inside a LINQ expression is unsupported:
var contacts = await _client.Contacts.Where(contact => contact.Interactions.Last().WebVisit().SiteName == value);

Timespan

You cannot use Timespan with a query that combines the OfType operator AND a Timespan property (for example, Hours, Minutes, Seconds, and so on).

Supported:

events.OfType<SomeEventType>(e => e.SomeTypeTimeSpanField > TimeSpan.FromHours(2))

Not supported:

events.OfType<SomeEventType>(e => e.SomeTypeTimeSpanField.Hours > 10)

Repeated names in paths to complex lists

The following queries are unsupported because Path.To.Nested is the same for both lists:

i.Scores().Scores.Any(s=>s.Path.To.Nested.Any())
i.ProfileScores().ProfileScores.Any(s=>s.Path.To.Nested.Any())

Azure Search provider limitations

The following limitations are specific to the Azure Search provider for xConnect search:

Limitations of Azure Search providers:

Scenario

Limitation

contact.Interactions.Any()

Azure Search provider does not support joins.

For more information, see Work with search and Search contacts (includes examples with and without joins).

Important

This Azure Search limitation affects which segmentation rules you can use. For example, you cannot filter contacts by email events (such as opening an email or clicking a link).

Partial text search

Not supported by the Azure Search provider. For example:

client.Contacts.Where(c => c.TextMatch("Mar"))

Azure Search list field limitations

The following table relates to complex type limitations in Azure Search.

9.0 Update 2

9.0 Update 2 introduces improvements to comparisons within lists of complex types. The following shows the operator support for these types:

Azure Search list field support matrix for 9.0 Update 2:

Types

==

||

&&

!

>

>=

<

<=

!=

Nested lists of strings, enums, or Guids

Yes

Yes

Yes

Yes

No

No

No

No

No

Nested lists of complex types or other simple types such as int or float

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

The following gives examples of operator usage for these types:

Azure Search list field examples for 9.0 Update 2:

Types

Examples

Nested lists of strings, enums, or Guids

Not supported:

c=>c.SomeFacet().SomeList.Any(e=>e!="hello")
c=>c.SomeFacet().SomeList.Any(e=>e!="hello"||e!="world")

Supported:

c=>c.SomeFacet().SomeList.Any(e=>e=="hello")
c=>c.SomeFacet().SomeList.Any(e=>e=="hello"||e=="world")

Nested lists of complex types or other simple types such as int or float

Supported:

c=>c.SomeFacet().SomeList.Any(e=>e.Property1>2)
c=>c.SomeFacet().SomeList.Any(e=>e.Property1!=2)
c=>c.SomeFacet().SomeList.Any(e=>e.Property1==2&&e.Property2=="string")
c=>c.SomeFacet().SomeList.Any(e=>e.Property1==2||e.Property2=="string")

A list that contains another list

You can use a nested Any() to reach the nested list.

Supported:

someList.Any(v=>v.NestedList.Any(u=>u.SomeField==2))

Nested lists of strings, enums, or Guids, inside the Any() predicate

You can use == and || inside the Any() predicate.

Supported:

c=>c.SomeFacet().SomeList.Any(e=>e=="hello")
c=>c.SomeFacet().SomeList.Any(e=>e=="hello"||e=="world")

The Any() that follows an OfType<T> call

It refers to fields of the exact type or the base class.

Supported:

i=>i.Events.OfType<Outcome>().Any(o=>o.MonetaryValue>10)
i=>i.Events.OfType<Outcome>().Any(o=>o.DefinitionId==someId)

9.0 Initial Release and 9.0 Update 1

The following shows the operator support for these types:

Azure Search list field support for 9.0 Initial Release and 9.0 Update 1:

Types

==

||

&&

!

>

>=

<

<=

!=

Nested lists inside the Any() predicate

Yes

No

No

No

No

No

No

No

No

The following gives examples of operator usage for these types:

Azure Search list field examples for 9.0 Initial Release and 9.0 Update 1:

Types

Examples

A list that contains another list

You can use a nested Any() to reach the nested list.

Supported:

someList.Any(v=>v.NestedList.Any(u=>u.SomeField==2))

Nested lists inside the Any() predicate

Not supported:

c=>c.SomeFacet().SomeList.Any(e=>e.Property1>2)
c=>c.SomeFacet().SomeList.Any(e=>e.Property1!=2)
c=>c.SomeFacet().SomeList.Any(e=>e.Property1==2&&e.Property2=="string")
c=>c.SomeFacet().SomeList.Any(e=>e.Property1==2||e.Property2=="string")

Supported:

MyListProperty.Any(v=>v.SomeField==2)
c=>c.SomeFacet().SomeList.Any(e=>e.Property1==2)||
c=>c.SomeFacet().SomeList.Any(e=>e.Property2=="string")

The Any() that follows an OfType<T> call

You can only refer to fields of the exact type that was specified, not the base class.

Not supported:

i=>i.Events.OfType<Outcome>().Any(o=>o.MonetaryValue>10)

Note

Even though MonetaryValue is a property of Outcome, you cannot use Any() with >).

i=>i.Events.OfType<Outcome>().Any(o=>o.DefinitionId==someId)

Note

DefinitionId is a property of a base class, not of Outcome.