coronabytes / dotnet-arangodb

.NET Driver for ArangoDB
Apache License 2.0
66 stars 18 forks source link

LINQ filtering methods #36

Closed Mrjuanblack closed 2 years ago

Mrjuanblack commented 2 years ago

Hello,

I'm having some issues with the LINQ implementation, specifically the .Where() method. I'm trying to filter some data using methods like:

.Where(x => x.Contains("string")) or .Where(x => x.Id.Equals(id))

Here's an example:

var q = await arango.Query<AnotherTestPerson>("TestDB").Where(x => x.Fullname.Contains("D")).FirstOrDefaultAsync();

Is there any possibility for getting support for these methods in the future? For now I have to convert the arango IQueryable to a list, then cast it again as a IQuearyable to access those methods.

coronabytes commented 2 years ago

Just rewrite them with

.Where(x => Aql.Contains(x.Name, "D"))

or

.Where(x => x.Id == id)

Supporting the other notations should be possible though.

Mrjuanblack commented 2 years ago

So calling methods normally in LINQ need to be done via the Aql functions? Or it's just the ones I listed here? I haven't tested other methods.

coronabytes commented 2 years ago

Yeah for now use the Aql. functions as they are bound to work natively - the ones with variable length params are broken though need to reqrite them with 1..5 named params or so

Just noticed even a basic list.Contains(y.Id) needs to be written as Aql.Position(list, x.Prop)

if any aql function is missing you can write one yourself with

public partial class AqlCustom
{
        private static Exception E => new NotImplementedException();

        [AqlFunction("FNV64")]
        public static string Fnv64(object value)
        {
            throw E;
        }
}
jannesiera commented 2 years ago

Hi @coronabytes ,

I'm working together with @Mrjuanblack on a project where we use this project to integrate with Arango. Thank you for your feedback so far.

The problem we are facing is that we need to integrate with a number of clients through a LINQ abstraction. They are currently depending on this abstraction to make things work with other databases and we should be able to just swap the implementation to one supporting Arango without breaking the interface. Because of that, it is not feasible to rely on Aql helpers -- methods like 'Contains' should work like in any other LINQ implementation.

What is the underlying reason for the current implementation through Aql helpers? And what kind of work would need to be done to support things like '.Contains' directly? We are happy to contribute to the project to get this to work but need some pointers for where to start.

Looking forward to working with you on this.

coronabytes commented 2 years ago

Well the LINQ code is basically just a fork of the first Arango .NET driver. (https://github.com/ra0o0f/arangoclient.net) Relinq should be able to quite easily support String. Math. and Date. functions, if its GroupBy you are looking for thats gota be a challenge, but contributions are welcome,

I'll try to add String.contains and then the rest is just copy pasta.

coronabytes commented 2 years ago

Ok got you a starting point https://github.com/coronabytes/dotnet-arangodb/tree/LinqMethods

the tricky part was finding out how to move the <x.Name>.Contains inside the Arguments, but thats seems to work, Please do not map StartsWith, EndsWith, Contains with LIKE Operator, because of % injection, use the native aql methods

also try x.Name.ToLower().Trim().Contains() and so on EDIT: chaining string methods looking good with intial code

jannesiera commented 2 years ago

@coronabytes awesome. We'll start working on this on a fork (after the holidays probably).