Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cosmos: Translate string.Contains, StartsWith, EndsWith with ComparisonType #25250

Closed
aguang-xyz opened this issue Jul 13, 2021 · 5 comments · Fixed by #33936
Closed

Cosmos: Translate string.Contains, StartsWith, EndsWith with ComparisonType #25250

aguang-xyz opened this issue Jul 13, 2021 · 5 comments · Fixed by #33936
Assignees
Labels
area-cosmos area-query closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported type-enhancement
Milestone

Comments

@aguang-xyz
Copy link

Description

The CONTAINS function of Cosmos DB supports case-insensitive searching. So I'm assuming that in EF Core with Cosmos Provider, we should be able to use string.contains with comparisionType specified. But when I try to do that, I got a translation failure.

My code

var keyword = "xxx";
var count = _dbContext<ProductDAO>()
                      .Where(product => product.Name.Contains(keyword, StringComparison.OrdinalIgnoreCase))
                      .Count();

Stack traces

System.InvalidOperationException
The LINQ expression 'DbSet<ProductDAO>()
    .Where(d => d.Name.Contains(
        value: __word_0, 
        comparisonType: OrdinalIgnoreCase))' could not be translated. Additional information: Translation of method 'string.Contains' failed. If this method can be mapped to your custom function, see https://go.microsoft.com/fwlink/?linkid=2132413 for more information. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
   at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.<VisitMethodCall>g__CheckTranslated|15_0(ShapedQueryExpression translated, <>c__DisplayClass15_0& )
   at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.Cosmos.Query.Internal.CosmosQueryableMethodTranslatingExpressionVisitor.Visit(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.Cosmos.Query.Internal.CosmosQueryableMethodTranslatingExpressionVisitor.Visit(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass9_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
   at System.Linq.Queryable.Count[TSource](IQueryable`1 source)

Include provider and version information

EF Core version: 5.0.7
Database provider: Microsoft.EntityFrameworkCore.Cosmos:5.0.7
Target framework: NET 5.0
Operating system: macOS Big Sur 11.4
IDE: Rider 2021.1

@roji
Copy link
Member

roji commented Jul 13, 2021

We should probably take a look at Cosmos case sensitivity in general.

For relational databases we don't support StringComparison since collations are a much better fit. However, in Cosmos there's no concept of a column collation, and functions such as CONTAINS and even STRINGEQUALS support specifying case-sensitivity as a flag.

One thing I'm not sure about, is whether indexes are used for both case-sensitive and insensitive matching (double-indexing?). Some resources include this and this.

Bottom line - it seems right to translate StringComparison.OrdinalIgnoreCase as proposed.

@svrooij
Copy link

svrooij commented Jul 13, 2021

I just stumbled upon this same problem, maybe there is a solution around the corner. Since Cosmos DB CONTAINS actually has support for case-insensitivity, as the third argument.

This pr added support for the current CONTAINS implementation.

Mind that this page states it's cheaper (RU wise) to use StartsWith but that should be up to yourself.

@roji
Copy link
Member

roji commented Jul 13, 2021

Mind that this page states it's cheaper (RU wise) to use StartsWith but that should be up to yourself.

Thanks for this link - that's helpful. Though CONTAINS and StartsWith are two different functions, with different usages.

@AndriySvyryd AndriySvyryd added this to the Backlog milestone Jul 13, 2021
@roji roji changed the title [EF Core Cosmos] Translation of method 'string.Contains' with comparisonType failed. Cosmos: Translation of method 'string.Contains' with comparisonType failed. Aug 28, 2021
@roji roji changed the title Cosmos: Translation of method 'string.Contains' with comparisonType failed. Cosmos: Translate string.Contains, StartsWith, EndsWith with ComparisonType May 9, 2022
@chajere

This comment was marked as resolved.

@roji

This comment was marked as resolved.

roji added a commit to roji/efcore that referenced this issue Jun 9, 2024
roji added a commit to roji/efcore that referenced this issue Jun 9, 2024
@roji roji self-assigned this Jun 9, 2024
@roji roji modified the milestones: Backlog, 9.0.0 Jun 9, 2024
@roji roji added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Jun 9, 2024
roji added a commit to roji/efcore that referenced this issue Jun 9, 2024
@ajcvickers ajcvickers modified the milestones: 9.0.0, 9.0.0-preview6 Jun 21, 2024
@roji roji modified the milestones: 9.0.0-preview6, 9.0.0 Oct 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-cosmos area-query closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported type-enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants