-
Notifications
You must be signed in to change notification settings - Fork 359
Description
Describe the bug
It appears that the library fails to parse a request URL that computes a custom property using the $compute query option and includes the computed property to the $select query option.
Consider the following request URL.
GET /Collection1
?$compute=graph.VectorDistance(contentVector, [1, 2, 3]) as SimilarityScore
&$select=Id, Title, SimilarityScore
In this case SimilarityScore is not a property defined on the entity type, but computed dynamically from the $compute expression. When I try to parse this URL, I get an error stating that it could not find the SimilarityScore property on the type. Is this a bug, feature gap, or by design?
I also removed the $select query option to see if the error would go away:
GET /Collection1
?$compute=graph.VectorDistance(contentVector,[1,2,3]) as SimilarityScore
But I got an error saying that the parameter to the VectorDistance function is not a single-valued parameter. So it seems like the library also does not support having a collection as the parameter of a function.
The argument for an invocation of a function with name 'graph.VectorDistance' is not a single value. All arguments for this function must be single values
If this is not supported by OData or not a bug, is there an alternative construct we can use to represent vector search queries?
Assemblies affected
Microsoft.OData.Core 8.4.0
Steps to Reproduce
Create a new console application with the following code. Make sure to also install Microsoft.OData.Core 8.4.0.
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Csdl;
using Microsoft.OData.UriParser;
using System.Text;
Console.WriteLine("Hello, World!");
var schema =
"""
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="4.0"
xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
<edmx:DataServices>
<Schema Namespace="graph" xmlns="http://docs.oasis-open.org/odata/ns/edm">
<!-- Entity Type -->
<EntityType Name="Item">
<Key>
<PropertyRef Name="Id"/>
</Key>
<Property Name="Id" Type="Edm.String" Nullable="false"/>
<Property Name="Title" Type="Edm.String" Nullable="true"/>
<Property Name="contentVector" Type="Collection(Edm.Double)" Nullable="false"/>
</EntityType>
<Function Name="VectorDistance" IsComposable="true">
<Parameter Name="vector1" Type="Collection(Edm.Double)" />
<Parameter Name="vector2" Type="Collection(Edm.Double)" />
<ReturnType Type="Edm.Double" />
</Function>
<!-- Entity Container -->
<EntityContainer Name="DefaultContainer">
<EntitySet Name="Collection1" EntityType="graph.Item" />
</EntityContainer>
<!-- Custom Function -->
</Schema>
</edmx:DataServices>
</edmx:Edmx>
""";
var stream = new MemoryStream(Encoding.UTF8.GetBytes(schema));
var reader = System.Xml.XmlReader.Create(stream);
var model = CsdlReader.Parse(reader);
var serviceRoot = new Uri("https://example.com/");
var fullUri = new Uri(serviceRoot, "Collection1?$compute=graph.VectorDistance(contentVector,[1,2,3]) as SimilarityScore&$select=Id,Title,SimilarityScore");
// Parse the URI
var fn = model.FindDeclaredOperations("graph.VectorDistance").First();
CustomUriFunctions.AddCustomUriFunction("graph.VectorDistance", new FunctionSignatureWithReturnType(fn.GetReturn().Type, fn.Parameters.Select(p => p.Type).ToArray()));
var parser = new ODataUriParser(model, serviceRoot, fullUri);
var parsedUri = parser.ParseUri();
// Display parsed structure
Console.WriteLine("Parsed Path: " + parsedUri.Path.ToString());
if (parsedUri.Compute != null)
{
Console.WriteLine("Compute expressions:");
foreach (var expr in parsedUri.Compute.ComputedItems)
{
Console.WriteLine($" {expr.Expression} AS {expr.Alias}");
}
}
if (parsedUri.SelectAndExpand != null)
{
Console.WriteLine("Selected properties:");
foreach (var sel in parsedUri.SelectAndExpand.SelectedItems)
{
Console.WriteLine(" " + sel.ToString());
}
}
Console.WriteLine("Parsing complete!");Then run the code.
Expected behaviour
The query options should be correctly parsed, and the sample app above should print the projected select items.
Actual behaviour
I got an exception saying that the property SimilarityScore could not be found. This is surprising, I believe the $select query option should be able to handle properties created by $compute.
Could not find a property named 'SimilarityScore' on type 'graph.Item'.
at Microsoft.OData.UriParser.SelectPathSegmentTokenBinder.ConvertNonTypeTokenToSegment(PathSegmentToken tokenIn, IEdmModel model, IEdmStructuredType edmType, ODataUriResolver resolver, BindingState state) in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\Binders\SelectPathSegmentTokenBinder.cs:line 90
at Microsoft.OData.UriParser.SelectExpandBinder.ProcessSelectTokenPath(PathSegmentToken tokenIn) in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\Binders\SelectExpandBinder.cs:line 694
at Microsoft.OData.UriParser.SelectExpandBinder.GenerateSelectItem(SelectTermToken tokenIn) in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\Binders\SelectExpandBinder.cs:line 276
at Microsoft.OData.UriParser.SelectExpandBinder.Bind(ExpandToken expandToken, SelectToken selectToken) in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\Binders\SelectExpandBinder.cs:line 153
at Microsoft.OData.UriParser.SelectExpandSemanticBinder.Bind(ODataPathInfo odataPathInfo, ExpandToken expandToken, SelectToken selectToken, ODataUriParserConfiguration configuration, BindingState state) in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\Binders\SelectExpandSemanticBinder.cs:line 37
at Microsoft.OData.UriParser.ODataQueryOptionParser.ParseSelectAndExpandImplementation(String select, String expand, ODataUriParserConfiguration configuration, ODataPathInfo odataPathInfo) in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\ODataQueryOptionParser.cs:line 451
at Microsoft.OData.UriParser.ODataQueryOptionParser.ParseSelectAndExpand() in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\ODataQueryOptionParser.cs:line 236
at Microsoft.OData.UriParser.ODataUriParser.ParseSelectAndExpand() in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\ODataUriParser.cs:line 322
at Microsoft.OData.UriParser.ODataUriParser.ParseUri() in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\ODataUriParser.cs:line 485
at Program.<Main>$(String[] args) in C:\repos\tinker\ODataAggregationExample\ODataAggregationExample\Program.cs:line 58
After removing the $select query option, I got the following exception:
The argument for an invocation of a function with name 'graph.VectorDistance' is not a single value. All arguments for this function must be single values.
at Microsoft.OData.UriParser.FunctionCallBinder.ValidateArgumentsAreSingleValue(String functionName, List`1 argumentNodes) in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\Binders\FunctionCallBinder.cs:line 82
at Microsoft.OData.UriParser.FunctionCallBinder.BindAsUriFunction(FunctionCallToken functionCallToken, List`1 argumentNodes) in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\Binders\FunctionCallBinder.cs:line 306
at Microsoft.OData.UriParser.FunctionCallBinder.BindFunctionCall(FunctionCallToken functionCallToken) in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\Binders\FunctionCallBinder.cs:line 238
at Microsoft.OData.UriParser.MetadataBinder.BindFunctionCall(FunctionCallToken functionCallToken) in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\Binders\MetadataBinder.cs:line 346
at Microsoft.OData.UriParser.MetadataBinder.Bind(QueryToken token) in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\Binders\MetadataBinder.cs:line 186
at Microsoft.OData.UriParser.ComputeBinder.BindComputeExpressionToken(ComputeExpressionToken token) in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\Binders\ComputeBinder.cs:line 38
at Microsoft.OData.UriParser.ComputeBinder.BindCompute(ComputeToken token) in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\Binders\ComputeBinder.cs:line 29
at Microsoft.OData.UriParser.ODataQueryOptionParser.ParseComputeImplementation(String compute, ODataUriParserConfiguration configuration, ODataPathInfo odataPathInfo) in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\ODataQueryOptionParser.cs:line 651
at Microsoft.OData.UriParser.ODataQueryOptionParser.ParseCompute() in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\ODataQueryOptionParser.cs:line 367
at Microsoft.OData.UriParser.ODataUriParser.ParseCompute() in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\ODataUriParser.cs:line 471
at Microsoft.OData.UriParser.ODataUriParser.ParseUri() in D:\a\_work\1\s\src\Microsoft.OData.Core\UriParser\ODataUriParser.cs:line 490
at Program.<Main>$(String[] args) in C:\repos\ODataAggregationExample\ODataAggregationExample\Program.cs:line 58
Additional details
Optional, details of the root cause if known. Delete this section if you have no additional details to add.