Coder Social home page Coder Social logo

nredisgraph's Issues

CallProcedure deserialization is not working with Read-Only queries

We are using a Redis graph read-only replica and performing read-only queries. In standard scenarios when the result is a specific value like a string or long there aren't any problems, but in the case when we are expecting nodes, the deserialization is calling inside it a 'GRAPH.QUERY' and the read-only replica which is only accepting 'GRAPH_RO.QUERY' is throwing an exception.

The full path to the method is ResultSet>RecordIterator>DeserializeScalar>DeserializeNode>_graphCache.GetLabel>_labels.GetCachedData>GetProcedureInfo>CallProcedure

Production usage

Hi,
For now, I am using a nodejs microservice to communicate with redisgraph from c#, I'm thinking to switch to this library.

  1. Is it production-ready?
  2. Are you planning to continue and maintain it?

Thanks

Need to support nested Records in the Result Set

In a query like this
MATCH p = (r)-[e]->(d) RETURN { nodes: nodes(p), edges: relationships(p) } LIMIT 2

There doesn't appear to be a way to decode the result.
ToDictionary on the returned RedisResult will give you a set of Key Value pairs, so I assume this is possible.

Library does not lend itself to unit testing

I am attempting to implement unit tests of a repository that uses NRedisGraph to access my Redis data. As one should always do for unit testing, I am mocking/faking al ldependencies, which includes objects from NRedisGraph. However, the library is too hard-coded and makes this impossible:

  1. Because the only way to create the graph object is via a new command (no abstract factory, no interface for dependency injection, etc.), I had to wrap the graph object in an adapter so that it would be unit testable.
  2. My query returns the ResultSet from the graph object's QueryAsync function. However, this object is sealed and internal. However, since it implements IEnumerable<Record>, I could create that enumerable and cast it to ResultSet when needed. Further cumbersome, but at least doable.
  3. The constructors for the Record are all internal, so I cannot instantiate a new one when setting up my mocks in my test. The class is sealed, which means I cannot extend it. It implements no interfaces and isn't abstract, so I can't mock it directly. This means that I cannot, in any way, shape, or form, create a Record object in a unit-test appropriate way. Therefore, all the other earlier work is for naught.

Ideally, we would have interfaces for the RedisGraph object, so it can be mockable at the root. Barring that, there needs to at least be 1 public constructor for the Record object, so they can be instantiated for mocks in a unit test.

Below is an example of my test:

        [Test]
        public async Task GetUserOrganizationPoliciesAsync_SingleScope_ReturnsUserPolicies()
        {
            //Arrange
            var mockGraph = new Mock<IRedisGraphAdapter>();
            _mockRedisGraphFactory.Setup(f => f.BuildAsync(0)).ReturnsAsync(mockGraph.Object);

            var mockRecord = new Mock<Record>();
            var policies = new[] { "my:policy", "my:other:policy" };
            mockRecord.Setup(r => r.GetString("r.policies")).Returns(JsonConvert.SerializeObject(policies));

            IEnumerable<Record> records = new[]
            {
                mockRecord.Object,
            };

            var queries = new Dictionary<string, IDictionary<string, object>>();
            mockGraph
                .Setup(g => g.QueryAsync("auth", It.IsAny<string>(), It.IsAny<Dictionary<string, object>>()))
                .Callback((string d, string q, IDictionary<string, object> p) => queries[q] = p)
                .ReturnsAsync((ResultSet)records);

            //Act
            var result = await _userPolicyCacheRepository.GetUserOrganizationPoliciesAsync(9266, 90210);

            //Assert
            Assert.That(result.ErrorMessage, Is.Null);
            Assert.That(result.Success, Is.True);
            Assert.That(result.Policies, Is.EqualTo(policies));

            mockGraph.Verify(g => g.QueryAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Dictionary<string, object>>()), Times.Once);
            var policyQuery = "MATCH (r:Role)-[:ASSIGNED_TO { user_id: $userId }]-(s:Scope)-[:INHERITS_FROM*0..3]->(:Scope { id: $scopeId }) " +
                               "RETURN r.policies " +
                               "UNION " +
                               "MATCH (:Scope { id: $scopeId })-[:INHERITS_FROM*0..3]->(s:Scope)-[:ASSIGNED_TO { user_id: $userId }]-(r:Role) " +
                               "RETURN r.policies";

            Assert.That(queries, Has.Count.EqualTo(1)
                .And.ContainKey(policyQuery));
            Assert.That(queries[policyQuery], Has.Count.EqualTo(2)
                .And.ContainKey("scopeId")
                .And.ContainKey("userId"));
            Assert.That(queries[policyQuery]["scopeId"], Is.EqualTo(90210));
            Assert.That(queries[policyQuery]["userId"], Is.EqualTo(9266));
        }

Obsolete attribute for RedisGraph 2.1

Hello, I noticed the following attribute in the code:

[Obsolete("SchemaType is no longer supported after RedisGraph 2.1 and will always return COLUMN_SCALAR")]

Is there a branch I could use where this is fixed ? It seems the whole deserialization in the ResultSet will not work anymore starting at 2.1.

How to specify the password used to connect?

I created a new Redis Graph on https://app.redislabs.com/ and it has a random password that the service created.

I tried to connect to it:

var muxr = ConnectionMultiplexer.Connect("[mydatabase].azure.cloud.redislabs.com:13788");// ("127.0.0.1");

But it throws this Exception:

StackExchange.Redis.RedisConnectionException: 'It was not possible to connect to the redis server(s). There was an authentication failure; check that passwords (or client certificates) are configured correctly. AuthenticationFailure (None, last-recv: 264)

How to specify the password that NRedisGraph uses to connect to the server?

Escaping query parameters

Hi,
I have some odd use-cases that I can't really put my finger on...
I am getting errors about un-escaped parameters, The bellow function received an object and internally convert it to a dictionary.
I have attached a screenshot that previews the dictionary.
ontop of that, I have some other use cases of emojis throwing the same errors, but I can really put my finger on it...

//success
services.RedisGraphClient.Execute("CREATE (a:Test {SomeString: $SomeString})", new { SomeString = "dsfdsfdss\"" });

//fails
services.RedisGraphClient.Execute("CREATE (a:Test {SomeString: $SomeString})", new { SomeString = "ds\" fdsfdss\"" });
//fails
services.RedisGraphClient.Execute("CREATE (a:Test {SomeString: $SomeString})", new { SomeString = "dsfdsfdss\"#" });

Thanks

image

Support map as parameter

I am running the following code:

var assignments = new (long ScopeId, long RoleId, long UserId)[]
{
    (123, 234, 345),
    (321, 432, 543),
}
var assignmentMaps = assignments.Select(a => new { scopeId = a.ScopeId, roleId = a.RoleId, userId = a.UserId }).ToArray();

await graph.QueryAsync(AuthGraphKey,
    query: "UNWIND $assignments AS assignment " +
            "MATCH (s:Scope { id: assignment.scopeId }), (r:Role { id: assignment.roleId }) " +
            "CREATE (s)-[:ASSIGNED_TO { user_id: assignment.userId }]->(r)",
    parameters: new Dictionary<string, object> {
            { "assignments", assignmentMaps },
    });

However, I get an exception from RedisGraph:

Exception: StackExchange.Redis.RedisServerException: errMsg: Invalid input 'a': expected ';', ':', a statement option, a query hint, a clause or a schema command line: 1, column: 1, offset: 0 errCtx: assignments=[{ scopeId = 1044, roleId = 1, userId = 12291 }, { scopeId = 1045... errCtxOffset: 0 at NRedisGraph.RedisGraph.QueryAsync(String graphId, String query) at GlobalEditAPI.Authorization.Core.Infrastructure.Data.IO.RedisGraphAdapter.QueryAsync(String graphId, String query, IDictionary2 parameters)`

From its formatting, I assume this is because when you provide a "map" type as a parameter, the utility calls .ToString() instead of serializing as json. We should do that serialization, so we can support map types.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.