What is RQL

    Imagine you have a data warehouse with a REST interface. Let it contain information about books and you want to list all the books. You can make a “books” method that will return us a list of books. But when displaying a list, there is usually pagination or lazy loading of data, and still wants to use it to filter and sort the data. When we add support for mobile devices, we still have a need to somehow limit the amount of data received without passing some of the fields. Almost any method of obtaining a list of objects should be able to understand all this information. lists are displayed using a special widget. And here the Resource Query Language comes to the rescue.

    Resource Query Language (RQL) is a query language designed for use in URIs when working with object-like data structures. Using RQL, the client can request from the server a list of objects that comply with certain rules, i.e., in fact, this is the syntax that describes how to request data. For example, the query selects all books Perumova attribution can be written as eq(author,Перумов)or in a conventional URL format author=Перумов.

    RQL can be considered mainly as a set of nested operators, each of which has many arguments. It is designed for a very simple, but extensible grammar, which can be used in a valid URL request.

    How to use RQL


    An RQL expression contains query functions or comparison operators connected by logical operators.

    Typical Scenarios


    First, we will analyze typical scenarios. For a better understanding, we will compare with similar commands in MongoDB.

    Let us have a list of books:

    [
    { title: "Эльфийский клинок", year: 1993, series: "Кольцо тьмы" },
    { title: "Чёрное копьё", year: 1993, series: "Кольцо тьмы" },
    { title: "Адамант Хенны", year: 1995, series: "Кольцо тьмы" },
    { title: "Воин Великой Тьмы", year: 1995, series: "Летописи Хьёрварда" }
    ]

    List all books from the Ring of Darkness series. In MongoDB, we would do it like this:

    db.users.find({series: "Кольцо тьмы"})

    in RQL, it will look like this:

    eq(series, "Кольцо тьмы")

    or

    series="Кольцо тьмы"

    Such a request will return three books to us.

    Now a more complex query: we need to display all the books of the Ring of Darkness series published in 1995.

    In MongoDB:

    db.users.find({series: "Кольцо тьмы", year: 1995})

    In RQL:

    eq(series, "Кольцо тьмы"),eq(year, 1995)

    Previous queries applied to simple objects. But documents can be very complex in structure. For example, add a new book to our library:

    { title: "Воин Великой Тьмы", year: 1995, series: "Летописи Хьёрварда", translations: { language: "English", title: "Godsdoom" } }

    A nested object with a key is defined here translations. And to find all the books translated into English, we need to use a period.

    In MongoDB:

    db.users.find({"translations.language": "English"})

    In RQL:

    eq(translations.language, "English")

    Over time, our library has grown. The list of books does not fit on the screen and we decided to display it page by page.

    In MongoDB, we can get the second ten records as follows:

    db.users.find().skip(10).limit(10)

    In RQL:

    limit(10,10)

    But showing page by page is not enough. I also want to sort the data.

    In MongoDB, this will be:

    db.users.find().sort({title: 1})

    In RQL:

    sort(+title) 

    Functions


    Basic functions of the standard:
    FunctionDescription
    in (,)Selects objects for which the value of the
    specified property is included in the specified array of properties.

    Example:
    in(name,(Silver,Gold))
    out (,)Selects objects for which the value of the specified property is not included in the specified array of properties.

    Example:
    out(name,(Platinum,Gold))
    limit (,)Returns the specified amount
    (number)
    of objects beginning with specific ( start ) position.

    Example:
    limit(0,2)
    sort ()Sorts the list of objects by the specified properties (the number of properties is unlimited). First, the list is sorted by the first of the specified properties, then by the second, and so on.
    The sorting order is determined by the prefix: + - ascending, - - descending.

    Example:
    sort(+memory,-diskspace)
    select ()Trims each object to a set of properties defined in arguments.

    Example:
    select(name,user)
    values ​​()Returns a set of values ​​from the specified field of all objects.

    Example:
    values(ve.name)
    count ()Returns the number of records.

    Example:
    in(name,(Silver,Gold))&count()
    max ()Returns the maximum value from the specified field of all objects.

    Example:
    max(ve.memory)
    min ()Returns the minimum value from the specified field of all objects.

    Example:
    min(ve.memory)

    More existing operators can be found in the official documentation .

    In APS technology, a new function has been added in RQL:
    FunctionDescription
    like (, )Searches for a given pattern in a given property. This
    function is similar to the SQL LIKE statement, although it uses a character *instead %. To determine the symbol itself in the pattern *, it must be percent-encoded, that is, it must be written %2Ainstead *, see examples. In addition, a symbol can be used in the pattern to ?indicate that any symbol in this position is valid.

    Examples:
    like(firstName,Jo*)
    like(firstName,*ohn)
    like(firstName,*oh*)
    like(firstName,Joh?)

    And three more APS-specific features:
    FunctionDescription
    implementing ()Returns a list of objects (resources and types) that implement the base type and include the base type itself.

    Example:
    implementing (http://aps-standard.org/samples/user-mgmt/offer/1.0)
    composing ()Returns a list of types that are implemented by the derived type, including the derived type itself.

    Example:
    composing(http://aps-standard.org/samples/user-mgmt/offer/1.0)
    linkedWith ()Returns a list of resources that are linked by the resource whose ID is specified as an argument. The APS controller looks for all links to resources, including internal system links. For example, an admin / owner / referrer actor that has access to a resource will also be considered a “linked” resource.

    Examples:
    linkedWith(220aa29a-4ff4-460b-963d-f4a3ba093a0a)

    implementing(http://aps-standard.org/types/core/user/service/1.0), linkedWith(220aa29a-4ff4-460b-963d-f4a3ba093a0a)

    Logical operators


    Boolean operators allow two or more query functions to be combined using Boolean logic. All standard logical operators have short aliases.
    OperatorAliasExamples
    and (,, ...)&
    ,
    and (limit(0,2),like(name,*L*))

    Value
    Selects the first two sentences whose names match a case-insensitive pattern.*L*
    or (,, ...)|
    ;
    or(like(description,*free*),in(name,(Silver,Gold)))

    Value
    Selects all sentences whose descriptions correspond to the pattern *free*, as well as those whose name Silver or Gold.

    In APS technology, RQL also added a new logical negation operator:
    OperatorExamples
    not ()not(like(name,*free*))

    Value
    Selects all sentences, with the exception of those whose name corresponds to the
    Habr and Gictimes - RQL pattern *free*.

    Note

    1. The operator and is an implicit top-level RQL operator. For example, the expression is http://hosting.com?and(arg1,arg2,arg3)equivalent http://hosting.com?arg1,arg2,arg3.
    2. The and operator has higher precedence than or. Therefore, when using aliases, you need to enclose the combined queries in parentheses, thereby determining the necessary processing order. Eg .implementing(),(prop1=eq=1|prop2=ge=2)

    Comparison operators


    The comparison operator is used to filter objects by comparing one of their properties with a given value .
    OperatorAliasExamples
    eq (,)= eq =eq(aps.status,aps:ready)
    aps.status=eq=aps:ready


    Value
    Selects all objects whose aps.statusvalue is aps:ready.
    ne (,)= ne =ne(aps.status,aps:ready)
    aps.status=ne=aps:ready


    Value
    Selects all objects whose aps.statusvalue is aps:ready.
    gt (,)= gt =implementing (http://aps-standard.org/samples/user-mgmt/offer), hardware.memory = gt = 1024)

    Value
    Selects all offers offering hardware.memorymore than 1024.
    ge (,)= ge =implementing (http://aps-standard.org/samples/user-mgmt/offer), hardware.memory = ge = 1024)

    Value
    Selects all offers offering hardware.memorymore than or equal to 1024.
    lt (,)= lt =implementing (http://aps-standard.org/samples/user-mgmt/offer), hardware.CPU.number = lt = 16)

    Value
    Selects all offers offering hardware.CPU.numberless than 16.
    le (,)= le =implementing (http://aps-standard.org/samples/user-mgmt/offer), hardware.CPU.number = le = 16)

    Value
    Selects all offers offering hardware.CPU.numberless than or equal to 16.

    String types are compared in lexicographic order .

    Values


    Query functions and comparison operators can contain the following values:

    • String (using URL encoding)
    • The numbers
    • Dates (in ISO UTC format without a colon)
    • Booleans
    • Value Functions

    Function values - are functions that return special values such as null, true, false or an empty string. All of them are applicable to certain types of data.
    Value functionApplicable TypesDescriptionsExamples
    null ()Any typeSet if value nullname=eq=null()
    true ()
    false ()
    BooleansSet if the value true orfalsedisabled=eq=false()
    empty ()StringSet if the string value is empty (not null, but does not contain any characters)addressPostal.extendedAddress=eq=empty()

    Using


    There are a large number of RQL parser implementations in various programming languages.

    The implementation in JavaScript, in addition to the parser, also contains an engine that can apply an RQL query to an array of objects.

    The original JavaScript RQL implementation is in npmjs: https://www.npmjs.com/package/rql

    An implementation with the functionality we added is also available through npm: https://www.npmjs.com/package/aps-rql

    Also popular now: