-
Notifications
You must be signed in to change notification settings - Fork 0
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
Further expansion of the relations system #6
Comments
There is a mix of |
I have been working on a prototype for this and for now what i can say is that it will most likely use a lua script so it can be Atomic and not cause any issues. |
An update on the relation system (0.13) The "spec"As of Nekdis 0.13 there will be a new option on the client called As for the functionality of the script itself it is divided into 2 categories each one with its sub categories. Creating relationsThere are 2 commands to create relations
Where:
First stepThe first step of creating a relation is creating the key where all the metadata will be saved, the type of the key can be either JSON or HASH depending on the command you use. Second StepThe second step is to append the id to the set that stores all the relations. Internally all it does is Getting all the relationsThe script also provides you a The syntax is:
Where:
This is easier to see if you look at the cli examples. How it worksThe first step is to get all the omitted ids from the set using Then we process them by fetching them, getting the Redis-cli ExampleLets setup 2 different users and create a relation between them with some metadata JSON.SET user:1 $ '{"name": "DidaS"}'
JSON.SET user:2 $ '{"name": "Leibale"}'
FCALL JSONCR 3 user:1 user:2 user:contacts:1 contacts '{"company": "Redis"}' After running this you will see 2 new keys on your database: A JSON key called {
"in": "user:1",
"out": "user:2",
"company": "Redis"
} And a set called To fetch all the relations you can run the following FCALL JSONGR 1 user:1 contacts Which for this example will return [
{
"name": "Leibale"
}
] You can note that metadata is not appended to the returning object, this is because metadata only exists so you can leverage An example of this would be: FT.CREATE exampleIdx ON JSON PREFIX 1 user:contacts: SCHEMA $.in AS in TAG $.out AS out TAG $.company AS company TEXT And then we want to search all contacts of user:1 that work on redis FT.SEARCH exampleIdx '@in:{user\:1} @company:redis' RETURN 1 out Nekdis example
I will translate the cli example into nekdis syntax so they will have exactly the same functionality. const userSchema = client.schema({
name: "string",
contacts: {
type: "relation",
index: true,
// Meta could be another schema just like the properties in an object type
meta: {
company: "text"
}
}
});
const userModel = client.model("User", userSchema);
// Im not using "createAndSave" so i can have the document without having to create and then fetch
const user1 = userModel.create({
name: "DidaS"
});
const user2 = userModel.create({
name: "Leibale"
});
await userModel.save(user1);
await userModel.save(user2);
// Im passing the record id just to exemplify that you can use either the document or an id/key
await userModel.relate(user1).to(user2.$record_id).as("contacts").with({ company: "Redis"}).exec();
await userModel.get(user1.$record_id, { withRelations: true });
/*
JSONDocument {
name: "DidaS"
contacts: [
{
name: "Leibale"
}
]
}
*/
await userModel.get(user1.$record_id, {
withRelations: true,
relationsConstrain: {
contacts: (r) => {
r.where("company").eq("redis");
}
}
}) Final notesThis is still a work in progress so if you have any ideas on how to improve please let me know. |
As the majority is probably aware now the RedisGraph module EOL was announced.
With this we pretty much lost our ability to use graphs and to have an easy way to create complex relations, thats where this expansion comes in.
This was actually my original idea for relations but i ended up simplifying it to what it is now because i though it was way to overcomplicated for a simple orm library specially when we had RedisGraph that could handle the majority of the work for us, with that said, the system i want to propose is not completely original and its pretty much a copy of how surrealdb handles relations internally.
The current system
This is the currently implemented "primitive" system, it just stores ids into an array and when you use auto-fetch it just loops through it and gets them, pretty simple and pretty straight forward.
The new proposal
The idea of expanding this system as said before would be to create a system just like surreal's and use the search functionality with it.
Where to start?
Well, to start it there is a huge decision that has to be made, this being, do we deprecate the current system and override it with the new one or do we keep the current one and just create a new type (relation) for the new system?
This is something i don't want to decide without getting any feedback since there might be some people who enjoy the simplicity of the current system and would not want to change to a more complex system that also comes with its downsides, which gets us to the next point.
What are the major downsides to this new approach?
As everyone knows by now, redis is a in-memory database which means its not the cheapest thing to run at scale and this system would bring noticeable memory usage, "why?" you mays ask, for that lets direct ourselves to the next point.
How does it work?
I will use some code examples to try and explain this as best as i can and to start we need to understand what really are what im calling here "complex relations".
Complex relations
Complex relations are relations that have and entry point and an exit point (in & out) and can contain metadata about that said relation. They would be represented entirely outside of the main document and would be represented as follow:
External representation
What do i exactly mean by a relation being represented externally?
This just means that the relation data would not be present in the main document and would be just a reference to an external id.
So lets imagine we have a user in our database with a friends list, this is how it would be represented internally:
This would also allow us to index this relations with RediSearch to have great query functionality without having to do much work ourselves.
The syntax
One of the biggest issues with this proposal is finding a syntax that everyone is happy with. The main idea is to just follow the
Builder Pattern
just like how we currently do for RediSearch.However having proper naming for defining this relations in a human readable and interactive way is the hard part.
This are my initial ideas for the syntax and im fully open to discussions about the topic.
Auto Fetching
Auto fetching is a more complicated topic in this case.
There are 2 ways i want to go about this:
Fetch-All
Fetch-Constrain
The text was updated successfully, but these errors were encountered: