What is relax-ql?
A simple query language for mongoodb. It base on mongoosejs. Everything is too easy to getting done your job. Write LESS, do MORE and Let's RELAX (after done :v)
Models
var ReviewSchema = ;const LocalBizSchema = name: String categories: String address: String rating: Number; const UserSchema = email: String displayName: String; const BrandSchema = name: String localBizs: ObjectId //Array of localbizs id of this brand; var Review = mongoose;var LocalBiz = mongoose;var User = mongoose;var Brand = mongoose; moduleexports = Review LocalBiz User Brand
Setup relax-ql
var ql = ;ql;
Example 1
You want get 10 reviews from database.
With mongoosejs:
Review ;
With relax-ql:
ql`*: Review().limit(10)` ;
Example 2
The code above is a simple query. And now, we will do with a more complex query. We will get 10 reviews from database and each review contain information of reviewer.
With mongoosejs:
Review ;
With relax-ql:
ql` *: Review().limit(10) authorDetail: User[this.author]`;
Example 3
Select and projection data
With mongoosejs:
Review ;
With relax-ql:
ql` *: Review().limit(10) content rating likes(slice: 3) author:= User[this.author] displayName email`;
So, what is relax-ql can do?
Begin with Find or FindOne
Find 10 reviews with rating = 5
ql`*: Review(rating == 5).limit(10)`;
or
ql`*: Review.find(rating == 5).limit(10)`
FindOne review with rating >= 3
ql`*: Review[rating == 5]`
or
ql`*: Review.findOne(rating == 5)`
Support query selectors
Comparison
== : $eq
!= : $ne
< : $lt
> : $gt
<= : $lte
>= : $gte
IN : $in
NIN : $nin
in : $in
nin : $nin
Logical
&& : $and
Element
EXISTS : $exists
TYPE : $type
exists : $exists
type : $type
Evaluation
MOD : $mod
REGEX : $regex
TEXT : $text
WHERE : $where
mod : $mod
regex : $regex
text : $text
where : $where
Array
ALL : $all
MATCH : $elemMatch
SIZE: $size
all : $all
match : $elemMatch
size: $size
Example query selectors
Example 1
likeNumber >= 5 && likeNumber < 100 && rating IN [2, 3] && comments EXISTS true
parse to
likeNumber: $gte: 5 $lt: 100 rating: $in: 2 3 comments: $exists: true
How to write a query selector
The bellow is rules for write query selector.
- Attribute always is left side of operator and value to compare must be right side of operator
- Currently, relax-ql not support OR logical operation. Only use and. But we absolutely write a complex query selector. I will show to you in next session.
- relax-ql support some type like: String, Number, Boolean, Array, Object, Regex. Example: "abc" or 'abc' is string, [1, 2, 3] is array of number, {a : 1} is an object, true or TRUE or False is booleam type and /abcd/ig is regex type.
- Can pass value by params, also pass a query selector by params. I'll show to you in next session.
Advance Find and FindOne
Find with complex query selector
ql`reviews: Review(likeNumber >= 5 && likeNumber < 100 && rating IN [2, 3] && comments EXISTS true)`
ql`reviews: Review()`
or use param
var reviewQuery = $or: likeNumber: 5 likeNumber: 4 rating: $in: 1 2 comments: $all: "$elemMatch" : likeNumber: $gt: 50 $lt: 100 "$elemMatch" : content : $regex: /abcd/i ql`reviews: Review()`
Find with options
relax-ql support limit, skip, sort (ASC, DESC)
ql`reviews: Review(likeNumber >= 5).limit(10).skip(10).DESC('rating').ASC('createdAt')`
Note: Sepecial support unlean optional. Because the query default call .lean() function. When we use unlean option, the query will not call .lean(). It very usefull when you defined some virtual atributes. Example:
Model:
var PersonSchema = name: first: String last: String toObject: virtuals: true toJSON: virtuals: true ;PersonSchema ; var Person = mongoose;
Don't use unlean()
ql`*: Person[]`;// display on screen/*{ name: { first: 'abc', last: 'def' }}*/
Use unlean() optional
ql`*: Person[].unlean()`;// display on screen/*{ name: { first: 'abc', last: 'def' }, displayName: 'abc def'}*/
Selection and projection
Selection
ql` reviews: Review(likeNumber >= 5) comments content rating`
or
ql` status: Status[] content user name gender `
It'll be
Status
Projection
Support
slice : $slice
SLICE : $slice
match : $elemMatch
MATCH : $elemMatch
meta : $meta
META : $meta
Example:
ql` status: Status[] content likes(3) comments(slice: 3)`
=>
Status
Nested query
Example:
ql` reviews: Review(rating >= 3).limit(5) author authorDetail: User[this.author] displayName localBiz:= LocalBiz[this.localBiz] name address likes *: User[this.$value] displayName relatedReviews: Review(localBiz == this.localBiz).limit(3) content author:= User[this.author] displayName`
Keyword:
- this: The pointer to parent
- this.$value: The value of parent
- := is select this attribute and result of query will overide to old value.
- '*' is result of child query will overide to parent value
How to access data of parent
Can you see the format of relax-ql like this:
ql` key_name: Model.function(query_selector).optional().optional() attr_selected attr_selected key_name: Model.function(query_selector).optional().optional() attr_selected attr_selected attr_selected:= Model.function(query_selector).optional().optional() attr_selected key_name: Model.function(query_selector).optional().optional() attr_selected attr_selected attr_selected *: Model.function(query_selector).optional().optional() attr_selected attr_selected `
We have two way to access to parent data.
- Use this
- It will access to nearest parent data
- Use key_name
- It will access to first parent match with key_name
Roadmap
- Support all logical: AND, OR, NOT
- Optimize query findOne
- Fix projection: likes({$slice: 3})