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

Allow label strings to be used in place of type/role objects wherever possible #614

Open
james-whiteside opened this issue Mar 21, 2024 · 0 comments

Comments

@james-whiteside
Copy link
Member

Problem to Solve

Using type/role objects in many concept API methods for instantiating types or interfaces is very inconvenient. Significant extra code is required, and several unnecessary round trips have to be made to create the objects. Consider the following query fragment, which creates a new book review entity.

match
$user ...
$book ...
?score ...
insert
$review isa review, has score ?score;
(executor: $user, action: $review) isa action-execution;
(review: $review, rated: $book) isa rating;

To perform the equivalent operation using the concept API, we must do the following:

def create_review(transaction: TypeDBTransaction, user: Entity, book: Entity, score_value: int) -> Entity:
    review_type = transaction.concepts.get_entity_type("review").resolve()
    action_execution_type = transaction.concepts.get_relation_type("action-execution").resolve()
    rating_type = transaction.concepts.get_relation_type("rating").resolve()
    score_type = transaction.concepts.get_attribute_type("score").resolve()
    action_role = action_execution_type.get_relates(transaction, "action").resolve()
    executor_role = action_execution_type.get_relates(transaction, "executor").resolve()
    review_role = rating_type.get_relates(transaction, "review").resolve()
    rated_role = rating_type.get_relates(transaction, "rated").resolve()
    review = review_type.create(transaction).resolve()
    action_execution = action_execution_type.create(transaction).resolve()
    action_execution.add_player(transaction, executor_role, user).resolve()
    action_execution.add_player(transaction, action_role, review).resolve()
    rating = rating_type.create(transaction).resolve()
    rating.add_player(transaction, review_role, review).resolve()
    rating.add_player(transaction, rated_role, book).resolve()
    score = score_type.put(transaction, score_value).resolve()
    review.set_has(transaction, score).resolve()
    return review

Here, several server calls have to be made to retrieve type/role objects solely to use them once within the scope as function arguments.

Proposed Solution

Allow all concept API methods that take type/role objects as arguments to also take label strings as arguments. In this case, the above example might look something like the following.

def create_review(transaction: TypeDBTransaction, user: Entity, book: Entity, score_value: int) -> Entity:
    review = transaction.concepts.create_entity("review").resolve()
    action_execution = transaction.concepts.create_relation("action-execution").resolve()
    action_execution.add_player(transaction, "action", review).resolve()
    action_execution.add_player(transaction, "executor", user).resolve()
    rating = transaction.concepts.create_relation("rating").resolve()
    rating.add_player(transaction, "review", review).resolve()
    rating.add_player(transaction, "rated", book).resolve()
    score = transaction.concepts.put_attribute("score", score_value).resolve()
    review.set_has(transaction, score).resolve()
    return review

As attribute insertions are idempotent, we could even allow set_has to take a label and value directly, though an attribute object would still be permissable.

review.set_has(transaction, "score", score_value).resolve()

This change to set_has would also be more in keeping with the revised approach of attributes as second-class citizens.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants