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

feat(c++): API design for multi-label support #614

Open
acezen opened this issue Sep 3, 2024 · 7 comments
Open

feat(c++): API design for multi-label support #614

acezen opened this issue Sep 3, 2024 · 7 comments
Labels
enhancement New feature or request

Comments

@acezen
Copy link
Contributor

acezen commented Sep 3, 2024

Describe the enhancement requested

TBF

Component(s)

C++

@acezen acezen added the enhancement New feature or request label Sep 3, 2024
@Elssky
Copy link
Contributor

Elssky commented Sep 3, 2024

Neo4j Cypher statements involving tags can be mainly divided into the following categories:

1. Creation

  • Create nodes with labels
CREATE (n:Label {property: value})
  • Add a label to existing nodes
MATCH (n) SET n:NewLabel

2. Deletion and Renaming

  • Remove all labels from nodes
MATCH (n) REMOVE LABELS(n)
  • Rename a label (by adding a new label and removing the old one)
MATCH (n:OldLabel) SET n:NewLabel REMOVE n:OldLabel

3. Querying and Filtering

  • Query nodes with a specific label
MATCH (n:Label) RETURN n
  • Query nodes with multiple labels
MATCH (n:Label1:Label2) RETURN n
  • Query nodes with a specific label and property
MATCH (n:Label {property: value}) RETURN n
  • Check if a node has a specific label
MATCH (n)
WHERE id(n) = <your_node_id> AND n:Label1
RETURN COUNT(n) > 0 AS hasLabel1

4. Statistics and Information

  • Count the number of nodes with a specific label
MATCH (n:Label) RETURN COUNT(n)
  • Query all labels
CALL db.labels() YIELD label RETURN label

@acezen
Copy link
Contributor Author

acezen commented Sep 3, 2024

LDBC SNB Cypher statements:

Querying and Filtering

  • bi-1
/*
:params { datetime: datetime('2011-12-01T00:00:00.000') }
*/
MATCH (message:Message)
WHERE message.creationDate < $datetime
WITH count(message) AS totalMessageCountInt // this should be a subquery once Cypher supports it
WITH toFloat(totalMessageCountInt) AS totalMessageCount
  • bi-2
MATCH (tag:Tag)-[:HAS_TYPE]->(:TagClass {name: $tagClass})
// window 1
OPTIONAL MATCH (message1:Message)-[:HAS_TAG]->(tag)
  WHERE $date <= message1.creationDate
    AND message1.creationDate < $date + duration({days: 100})
WITH tag, count(message1) AS countWindow1
// window 2
OPTIONAL MATCH (message2:Message)-[:HAS_TAG]->(tag)
  WHERE $date + duration({days: 100}) <= message2.creationDate
    AND message2.creationDate < $date + duration({days: 200})
WITH
  tag,
  countWindow1,
  count(message2) AS countWindow2
  • bi-3
/*
:params { tagClass: 'MusicalArtist', country: 'Burma' }
*/
MATCH
  (:Country {name: $country})<-[:IS_PART_OF]-(:City)<-[:IS_LOCATED_IN]-
  (person:Person)<-[:HAS_MODERATOR]-(forum:Forum)-[:CONTAINER_OF]->
  (post:Post)<-[:REPLY_OF*0..]-(message:Message)-[:HAS_TAG]->(:Tag)-[:HAS_TYPE]->(:TagClass {name: $tagClass})

@acezen
Copy link
Contributor Author

acezen commented Sep 4, 2024

LDBC SNB Gremlin statements:

Querying and Filtering

  • bi-2
g.V().has("TAGCLASS", "name", "$tagClass").in("HASTYPE").as("tag").in("HASTAG").hasLabel("POST", "COMMENT").union(    __.has("creationDate", P.gte($date).and(P.lt($ddate))).as("msg1"),    __.has("creationDate", P.gte($ddate).and(P.lt($dddate))).as("msg2")).group().by(select("tag")).by(    dedup("msg1").count().as("cnt1"),    dedup("msg2").count().as("cnt2")).select(expr("(@cnt2 - @cnt1)*(@cnt2 - @cnt1)")).as("diff").order().by(select("diff"), desc).by(select(keys).values("name"), asc).limit(100).select("cnt1", "cnt2", "diff").by().by().by()
  • bi-3
g.V().has("PLACE", "name", "$country").in("ISPARTOF").in("ISLOCATEDIN").as("person").in("HASMODERATOR").as("forum") .out("CONTAINEROF").in("0..5", "REPLYOF").endV().as("msg").out("HASTAG").out("HASTYPE").has("TAGCLASS", "name", "$tagClass").select("msg").group().by(select("forum").as("forum")).by(dedup().count().as("msgCnt")).order().by(select("msgCnt"), desc).by(select("forum").by("id"), asc).limit(20).select("forum", "msgCnt").by(valueMap("id", "title", "creationDate")).by()
  • bi-4
g.V().has("TAG", "name", "$tag").in("HASTAG").as("msg") .out("HASCREATOR").as("person") .union( select("msg").as("msg1"), select("msg").in("LIKES").as("like"), select("msg").in("REPLYOF").as("reply")) .group() .by(select("person")) .by( select("msg1").count().as("msgCnt"), select("like").count().as("likeCnt"), select("reply").count().as("replyCnt")) .select(keys).as("person") .select(expr("1*@msgCnt+2*@replyCnt+10*@likeCnt")).as("score") .order() .by(select("score"), desc) .by(select("person").by("id"), asc) .limit(100) .select("person", "replyCnt", "likeCnt", "msgCnt", "score") .by("id").by().by().by().by()

@Elssky
Copy link
Contributor

Elssky commented Sep 4, 2024

class VerticesCollection {
public:
    /**
     * @brief Query vertices with a specific label
     *
     * @param filter_label The label to query vertices by
     * @param graph_info A smart pointer to GraphInfo that contains details about the graph
     * @param type The type of vertices to query 
     * @return A VerticesCollection containing all vertices that have the specified label
     */
    static Result<std::shared_ptr<VerticesCollection>> verticesWithLabel(
        const std::string& filter_label, 
        const std::shared_ptr<GraphInfo>& graph_info, 
        const std::string& type);

    /**
     * @brief Query vertices with a specific label within a given collection
     *
     * @param filter_label The label to query vertices by
     * @param vertices_collection The collection of vertices to search within
     * @return A VerticesCollection containing all vertices from the specified collection that have the specified label
     */
    static Result<std::shared_ptr<VerticesCollection>> verticesWithLabel(
        const std::string& filter_label, 
        const std::shared_ptr<VerticesCollection>& vertices_collection);

    /**
     * @brief Query vertices with multiple labels
     *
     * @param filter_labels A vector of labels to query vertices by
     * @param graph_info A smart pointer to GraphInfo that contains details about the graph
     * @param type The type of vertices to query 
     * @return A VerticesCollection containing all vertices that have all of the specified labels
     */
    static Result<std::shared_ptr<VerticesCollection>> verticesWithMultipleLabels(
        const std::vector<std::string>& filter_labels, 
        const std::shared_ptr<GraphInfo>& graph_info, 
        const std::string& type);

    /**
     * @brief Query vertices with multiple labels within a given collection
     *
     * @param filter_labels A vector of labels to query vertices by
     * @param vertices_collection The collection of vertices to search within
     * @return A VerticesCollection containing all vertices from the specified collection that have all of the specified labels
     */
    static Result<std::shared_ptr<VerticesCollection>> verticesWithMultipleLabels(
        const std::vector<std::string>& filter_labels, 
        const std::shared_ptr<VerticesCollection>& vertices_collection);
  
    /**
     * @brief Query vertices with a specific label and properties
     *
     * @param filter_label The label to query vertices by
     * @param propery_filter_expr A shared pointers to Property filter expression that the vertices should match
     * @param graph_info A smart pointer to GraphInfo that contains details about the graph
     * @param type The type of vertices to query 
     * @return A VerticesCollection containing all vertices that have the specified label and match the given properties
     */
    static Result<std::shared_ptr<VerticesCollection>> verticesWithLabelAndProperty(
        const std::string& filter_label, 
        const std::shared_ptr<Expression> propery_filter_expr, 
        const std::shared_ptr<GraphInfo>& graph_info, 
        const std::string& type);

    /**
     * @brief Query vertices with a specific label and properties within a given collection
     *
     * @param filter_label The label to query vertices by
     * @param propery_filter_expr A shared pointers to Property filter expression that the vertices should match
     * @param vertices_collection The collection of vertices to search within
     * @return A VerticesCollection containing all vertices from the specified collection that have the specified label and match the given properties
     */
    static Result<std::shared_ptr<VerticesCollection>> verticesWithLabelAndProperty(
        const std::string& filter_label, 
        const std::shared_ptr<Expression> propery_filter_expr, 
        const std::shared_ptr<VerticesCollection>& vertices_collection);


};

class VertexIter {
    /**
     * @brief Check if the vertex has a specific label
     *
     * @param label The label to check for on the specified vertex
     * @return True if the vertex has the specified label, false otherwise
     */
    bool HasLabel(const std::string& label);
}

@yecol
Copy link
Contributor

yecol commented Sep 4, 2024

Please refers to the existing VerticesCollection, holding iterators would be better.

@yecol
Copy link
Contributor

yecol commented Sep 4, 2024

They should be static functions like Make I guess, rather than member functions of VerticesCollection

ref:

static Result<std::shared_ptr<VerticesCollection>> Make(

@Elssky
Copy link
Contributor

Elssky commented Sep 20, 2024

MATCH (n:Label {property: value}) RETURN n

1. Query nodes with a specific label

Cypher:

MATCH (n:Label) RETURN n

Gremlin:

g.V().hasLabel('Label')

2. Query nodes with multiple labels

Cypher:

MATCH (n:Label1:Label2) RETURN n

Gremlin:

g.V().hasLabel('Label1').hasLabel('Label2')

3. Query nodes with a specific label and property

Cypher:

MATCH (n:Label {property: value}) RETURN n

Gremlin:

g.V().hasLabel('Label').has('property', value)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants