• Platform
  • Language
  • Docs
  • Blog
  • Get Started
  • ConceptEngine Documentation

    Our blog post Introducing ConceptEngine gives an overview of what ConceptEngine is all about, and also lays out a simple example.

    ConceptML

    ConceptML is a minimalistic language to express connected data. It includes syntax for defining relationships and meta-relationships, as well as composing related concepts with its expansion syntax.

    What are Concepts?

    In ConceptEngine, data is represented in labeled hierarchical structures we call concepts. Here's one way to vizualize them:

    concept-engine
    named
    <<Concept Engine>>

    ConceptML: concept-engine [named <<Concept Engine>>]

    john-smith
    Person

    ConceptML: john-smith Person

    john-smith
    use
    concept-engine
    for-purpose
    knowledge-graph

    ConceptML: [john-smith [use concept-engine]] [for-purpose knowledge-graph]

    Atoms

    The simplest kind of concept is an atom, which is just a single token or a block of text enclosed with << and >>.

    These are examples of atoms:

    javascript
    typescript
    ProgrammingLanguage
    42
    <<December 30, 1985>>
    john-smith
    #some_hashtag
    

    Compounds

    A compound is a list of two or more concepts. You can embed compound concepts by enclosing them with [ and ].

    These are examples of compounds:

    javascript ProgrammingLanguage
    typescript superset-of javascript
    [john-smith knows javascript] since 1999
    

    The ability to include an arbitrary number of concepts, along with nesting them as deeply as you'd like, gives concepts extra expressiveness.

    Here's one example of deeply nested concepts:

    [mary-mullens disagrees [[jon-smith knows javascript] since 1999]] at <<March 7, 2022 10:35:00>>
    

    Here we're using nested concepts to represent metadata, which can be useful for higher-level tools that manage the data, such as content management systems. However, nesting concepts isn't just for metadata--it gives you the freedom to design your own grammars.

    There are many different ways you can represent information using concepts. Here are four ways of expressing once piece of information:

    john-smith knows javascript
    john-smith [knows javascript]
    [john-smith javascript] Knowledge
    knows john-smith javascript
    

    As long as there are distinct patterns between different kinds of information, it will work.

    Expansion Syntax

    Let's say we want to compose a set of related concepts. ConceptML provides expansion syntax to branch off multiple concepts within the flow of a composition.

    There are three kinds of expansion, which each involve surrounding concept fragments with brackets and separating each branch with a comma or newline:

    • Nested: []
    • Inline: {}
    • Parenthetical: ()

    Here's an example that involves all three:

    john-smith [
      Person
      knows {
        {javascript, typescript} (ProgrammingLanguage)
        {ms-word, ms-excel} (App, [created-by microsoft])
      }
    ]
    

    This expands into these concepts:

    john-smith Person
    john-smith [knows javascript]
    john-smith [knows typescript]
    john-smith [knows ms-word]
    john-smith [knows ms-excel]
    javascript ProgrammingLanguage
    typescript ProgrammingLanguage
    ms-word App
    ms-excel App
    ms-word [created-by microsoft]
    ms-excel [created-by microsoft]
    

    Below are the three types in detail.

    Nested Expansion

    Creates branches within a nested compound block.

    For example:

    mary wrote [
      javascript ProgrammingLanguage
      javascript #awesome
    ]
    

    This would expand to:

    mary wrote [javascript ProgrammingLanguage]
    mary wrote [javascript #awesome]
    

    Inline Expansion

    Creates branches within the flow of a concept definition.

    For example:

    john {knows, likes} javascript
    

    would expand to:

    john knows javascript
    john likes javascript
    

    Parenthetical Expansion

    Creates concepts outside the flow of concept definition, with the immediately preceding concept acting as the head of the expanded concepts.

    For example:

    john knows {javascript, typescript} (ProgrammingLanguage)
    

    This would expand to:

    john knows javascript
    john knows typescript
    javascript ProgrammingLanguage
    typescript ProgrammingLanguage
    

    Space API

    The Space API uses GraphQL to read, write, and match concepts using pattern matching. On top of pattern matching, it provides methods to project queried concepts into JSON structures.

    You can also store arbitrary strings (up to 25MB) against concepts.

    Because you can use concepts to represent just about any kind of information, and you can use the Space API's GraphQL fields to query and project them into custom payloads, ConceptEngine can act as an instant backend for all sorts of apps.

    Access

    URL

    Each space has its own GraphQL API. URLs follow this pattern:

    https://api.coeng.workers.dev/spaces/:spaceId/graphql

    You can find your space's URL by navigating to its API Access tab in the dashboard.

    Authorization

    In order to use the API, you must include a Bearer token in the Authorization header of your requests.

    First, create an access token in the API Access tab. You can then use that token to make requests. They follow this pattern:

    fetch('https://api.coeng.workers.dev/spaces/:spaceId/graphql', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: 'Bearer <token>',
      },
      body: JSON.stringify({
        query: 'query { concepts { key } }',
        variables: {}
      })
    });
    

    Concepts

    These are all of the queries, mutations, and fields related to the Concept type, which we'll cover in more depth in the sections below:

    type Query {
      concept(key: ID!): Concept
      concepts(query: ConceptsQuery = {}): [Concept!]!
    }
    
    type Mutation {
      addConcepts(input: AddConceptsInput!): [Concept!]!
      removeConcepts(keys: [String!]!): Int!
      updateConceptData(input: UpdateConceptDataInput!): Concept!
    }
    
    type Concept {
      key: ID!
      text: String!
      data: String
      parts: [Concept!]!
      contexts: [Concept!]!
    }
    

    List Concepts

    Type Definitions

    type Query {
      concepts(query: ConceptsQuery = {}): [Concept!]!
    }
    
    input ConceptsQuery {
      pagination: Pagination = {}
    }
    
    input Pagination {
      limit: Int = 100
      startKey: String
      endKey: String
    }
    

    Example

    Query:

    query {
      concepts(query: {
        pagination: {
          startKey: "docs"
          limit: 3
        }
      }) {
        key
      }
    }
    

    Result:

    {
      "data": {
        "concepts": [
          {
            "key": "docs-overview-page Page"
          },
          {
            "key": "docs-overview-page [named <<ConceptEngine Documentation>>]"
          },
          {
            "key": "docs-overview-page"
          }
        ]
      }
    }
    

    Get a Concept

    Type Definitions

    type Query {
      concept(key: ID!): Concept
    }
    

    Example

    Query:

    query {
      concept(key: "Post") {
        key
        contexts {
          key
        }
      }
    }
    

    Result:

    {
      "data": {
        "concept": {
          "key": "Post",
          "contexts": [
            {
              "key": "Post Type"
            },
            {
              "key": "intro-post Post"
            }
          ]
        }
      }
    }
    

    Get Concept Text

    Returns the key, but stripped of any surrounding << and >> brackets.

    Type Definitions

    type Concept {
      text: String!
    }
    

    Example

    Query:

    query {
      concept(key: "<<Introducing Concept Engine>>") {
        text
      }
    }
    

    Result:

    {
      "data": {
        "concept": {
          "text": "Introducing Concept Engine"
        }
      }
    }
    

    Get Concept Data

    Concepts also act as key-value pairs. You can access the stored value by using the Concept.data field.

    Type Definitions

    type Concept {
      data: String
    }
    

    Example

    Query:

    query {
      concept(key: "intro-post excerpt") {
        data
      }
    }
    

    Result:

    {
      "data": {
        "concept": {
          "data": "ConceptEngine is a blazing-fast data store for nested hypergraphs, a data model that goes even further than traditional graphs to capture highly connected data."
        }
      }
    }
    

    List Parts of a Concept

    Get all concepts that a concept is composed of.

    Type Definitions

    type Concept {
      parts: [Concept!]!
    }
    

    Example

    Query:

    query {
      concept(key: "intro-post [named <<Introducing ConceptEngine>>]") {
        parts {
          key
          parts {
            key
          }
        }
      }
    }
    

    Result:

    {
      "data": {
        "concept": {
          "parts": [
            {
              "key": "intro-post",
              "parts": []
            },
            {
              "key": "named <<Introducing ConceptEngine>>",
              "parts": [
                {
                  "key": "named"
                },
                {
                  "key": "<<Introducing ConceptEngine>>"
                }
              ]
            }
          ]
        }
      }
    }
    

    List Contexts of a Concept

    Get all concepts that a concept is a part of.

    Type Definitions

    type Concept {
      contexts: [Concept!]!
    }
    

    Example

    Query:

    query {
      concept(key: "intro-post") {
        contexts {
          key
        }
      }
    }
    

    Result:

    {
      "data": {
        "concept": {
          "contexts": [
            {
              "key": "intro-post Post"
            },
            {
              "key": "intro-post excerpt"
            },
            {
              "key": "intro-post [named <<Introducing ConceptEngine>>]"
            },
            {
              "key": "intro-post [published-on <<February 2, 2022>>]"
            },
            {
              "key": "intro-post [slug <<introducing-concept-engine>>]"
            },
            {
              "key": "intro-post [written-by eric-weber]"
            }
          ]
        }
      }
    }
    

    Add Concepts

    Type Definitions

    type Mutation {
      addConcepts(input: AddConceptsInput!): [Concept!]!
    }
    
    input AddConceptsInput {
      source: [String!]!
      interpolate: [Interpolation!] = []
    }
    
    input Interpolation {
      key: String!
      value: [String!]!
    }
    

    Example

    Mutation:

    mutation AddPost($post: String!, $slug: String!, $name: String!) {
      newConcepts: addConcepts(input: {
        source: "$post [Post, slug $slug, named $name]"
        interpolate: [
          { key: "$post", value: [$post] }
          { key: "$slug", value: [$slug] }
          { key: "$name", value: [$name] }
        ]
      }) {
        key
      }
    }
    

    Result:

    {
      "data": {
        "newConcepts": [
          {
            "key": "hello-world-post Post"
          },
          {
            "key": "hello-world-post [slug <<hello-world>>]"
          },
          {
            "key": "hello-world-post [named <<Hello World>>]"
          },
          {
            "key": "hello-world-post"
          },
          {
            "key": "slug <<hello-world>>"
          },
          {
            "key": "<<hello-world>>"
          },
          {
            "key": "named <<Hello World>>"
          },
          {
            "key": "<<Hello World>>"
          }
        ]
      }
    }
    

    Remove Concepts

    Type Definitions

    type Mutation {
      removeConcepts(keys: [String!]!): Int!
    }
    

    Example

    Mutation:

    mutation {
      removeConcepts(keys: ["test-post"])
    }
    

    Result:

    {
      "data": {
        "removeConcepts": 0
      }
    }
    

    Update Concept Data

    Type Definitions

    type Mutation {
      updateConceptData(input: UpdateConceptDataInput!): Concept!
    }
    
    input UpdateConceptDataInput {
      key: ID!
      data: String!
    }
    

    Example

    Mutation:

    mutation {
      concept: updateConceptData(input: {
        key: "test-post excerpt"
        data: "Just a test."
      }) {
        data
      }
    }
    

    Result:

    {
      "data": {
        "concept": {
          "data": "Just a test."
        }
      }
    }
    

    Pattern Matching

    ConceptEngine uses pattern matching in a similar way to SPARQL, in that it attempts to complete a set of patterns, which are composed of concepts and variables.

    For example:

    $person [Person, knows $topic (ProgrammingLanguage)]
    

    Find All Matches

    Type Definitions

    type Query {
      matches(query: MatchesQuery!): [RuleSetMatch!]!
    }
    
    input MatchesQuery {
      rules: [String!]!
      interpolate: [Interpolation!] = []
      pagination: Pagination = {}
    }
    

    Example

    Query:

    query {
      matches(
        query: {
          rules: [
            "$post [Post, named $name, written-by $author]"
          ]
          interpolate: [
            { key: "$author", value: "eric-weber" }
          ]
        }
      ) {
        post: keyOf(name: "$post")
      }
    }
    

    Result:

    {
      "data": {
        "matches": [
          {
            "post": "intro-post"
          }
        ]
      }
    }
    

    Find First Match

    Type Definitions

    type Query {
      match(query: MatchQuery!): RuleSetMatch
    }
    
    input MatchQuery {
      rules: [String!]!
      interpolate: [Interpolation!] = []
    }
    

    Example

    Query:

    query {
      match(
        query: {
          rules: [
            "$post [Post, named $name, written-by $author]"
          ]
          interpolate: [
            { key: "$author", value: "eric-weber" }
          ]
        }
      ) {
        post: keyOf(name: "$post")
      }
    }
    

    Result:

    {
      "data": {
        "match": {
          "post": "intro-post"
        }
      }
    }
    

    Get Match Variables

    Type Definitions

    type RuleSetMatch {
      variables: [VariableMatch!]!
    }
    
    type VariableMatch {
      name: ID!
      match: Concept!
    }
    

    Example

    Query:

    query {
      match(query: {
        rules: "$person Person"
      }) {
        variables {
          name
          match {
            key
          }
        }
      }
    }
    

    Result:

    {
      "data": {
        "match": {
          "variables": [
            {
              "name": "$person",
              "match": {
                "key": "eric"
              }
            }
          ]
        }
      }
    }
    

    Get Specific Variable

    Type Definitions

    type RuleSetMatch {
      valueOf(name: ID!): Concept!
    }
    

    Example

    Query:

    query {
      match(query: {
        rules: "$person Person"
      }) {
        person: valueOf(name: "$person") {
          key
        }
      }
    }
    

    Result:

    {
      "data": {
        "match": {
          "person": {
            "key": "eric"
          }
        }
      }
    }
    

    Get Key of Variable

    Type Definitions

    type RuleSetMatch {
      keyOf(name: ID!): String
    }
    

    Example

    Query:

    query {
      match(query: {
        rules: "$person Person"
      }) {
        personKey: keyOf(name: "$person")
      }
    }
    

    Result:

    {
      "data": {
        "match": {
          "personKey": "eric"
        }
      }
    }
    

    Get Text Value of Variable

    Type Definitions

    type RuleSetMatch {
      textOf(name: ID!): String
    }
    

    Example

    Query:

    query {
      match(query: {
        rules: "$person [Person, named $personName]"
      }) {
        name: textOf(name: "$personName")
      }
    }
    

    Result:

    {
      "data": {
        "match": {
          "name": "Eric"
        }
      }
    }
    

    Get Data of Variable

    Type Definitions

    type RuleSetMatch {
      dataOf(name: ID!): String
    }
    

    Example

    Query:

    query {
      posts: matches(query: {
        rules: "$post Post"
      }) {
        key: keyOf(name: "$post")
        content: dataOf(name: "$post")
      }
    }
    

    Result:

    {
      "data": {
        "posts": [
          {
            "key": "test-post",
            "content": "Just a test."
          }
        ]
      }
    }
    

    Subquery Matches

    Type Definitions

    type RuleSetMatch {
      matches(rules: [String!]!): [RuleSetMatch!]!
    }
    

    Example

    Query:

    query {
      posts: matches(query: {
        rules: "$post [Post]"
      }) {
        key: keyOf(name: "$post")
        tags: matches(rules: "$post $tag (Tag)") {
          key: keyOf(name: "$tag")
        }
      }
    }
    

    Result:

    {
      "data": {
        "posts": [
          {
            "key": "test-post",
            "tags": [
              {
                "key": "#coeng"
              },
              {
                "key": "#test"
              }
            ]
          }
        ]
      }
    }
    

    Subquery Single Match

    Type Definitions

    type RuleSetMatch {
      match(rules: [String!]!): RuleSetMatch
    }
    

    Example

    Query:

    query {
      posts: matches(query: {
        rules: "$post [Post]"
      }) {
        key: keyOf(name: "$post")
        author: match(rules: "$post [written-by $author]") {
          key: keyOf(name: "$author")
        }
      }
    }
    

    Result:

    {
      "data": {
        "posts": [
          {
            "key": "test-post",
            "author": {
              "key": "eric"
            }
          }
        ]
      }
    }
    

    Subquery Concepts

    Type Definitions

    type RuleSetMatch {
      concepts(rule: String!): [Concept!]!
    }
    

    Example

    Query:

    query {
      posts: matches(query: {
        rules: "$post Post"
      }) {
        tags: concept(rule: "$post $tag (Tag)") {
          key
        }
      }
    }
    

    Result:

    {
      "data": {
        "posts": [
          {
            "tags": {
              "key": "test-post #coeng"
            }
          }
        ]
      }
    }
    

    Subquery Single Concept

    Type Definitions

    type RuleSetMatch {
      concept(rule: String!): Concept
    }
    

    Example

    Query:

    query {
      posts: matches(query: {
        rules: "$post Post"
      }) {
        excerpt: concept(rule: "$post excerpt") {
          data
        }
      }
    }
    

    Result:

    {
      "data": {
        "posts": [
          {
            "excerpt": {
              "data": "Just a test."
            }
          }
        ]
      }
    }