I'm new to ArangoDB and javascript (and pretty much everything else too). I'm watching a tutorial that uses Vue, GraphQL, Mongoose and MongoDB. I would like to use a very similar technology stack, except with ArangoDB.
However, when using Arangojs (the javascript driver for ArangoDB), I find myself having to work a lot harder and write a lot more code to accomplish the same thing compared to the tutorial, and this difference comes down to Mongoose. I'm looking for a solution or development approach that will allow easy evolution and maintenance of the code base, above all else.
In particular, when defining a Mongoose schema, we can do things like this:
const UserSchema = new mongoose.Schema({
username: {
type: String,
required: true,
unique: true,
trim: true
},
//...
favorites: {
type: [mongoose.Schema.Types.ObjectId],
required: true,
ref: "Post"
}
});
The ref type provides a lot of convenience, for example. I guess I'm looking for something like Mongoose for ArangoDB and javascript, but I don't think such a thing exists. So I'm asking how (at a high level) can I approach my development to achieve a similar level of coding functionality.
For example, can GraphQL's SDL schemas achieve the same thing as a Mongoose Schema, and nearly as easily?
Is there a way to use a GraphQL schema across both the frontend and backend of a javascript application, eliminating javascript typeDefs and models in the process? The goal here, as suggested above, is to prioritize ease of working with the code as features are added and changes made to the project requirements.
Update: this looks like a similar question (without an answer):
Are there ways to populate a schema in Joi from another schema (like Mongoose does)? - Stack Overflow
Related
I'm using ArangoDB 3.4 and planning to use an MVC framework like Backbone.js (or whatever is recommended). Is there a way to auto-generate the models from the existing database to reduce the amount of boilerplate code I have to write by hand?
For example, I am looking at the aye-aye TodoMVC demo. It has this model:
const joi = require('joi');
exports.Model = {
_key: joi.string().optional(),
_id: joi.string().optional(),
_rev: joi.string().optional(),
completed: joi.boolean().optional(),
order: joi.number().optional(),
title: joi.string().optional()
};
Writing a few by hand is no problem. My database will ultimately require many of these models. Are there any tools that I can use with ArangoDB that will help automate this by producing scaffold code?
What I have in mind is possibly something like Python's inspectdb command:
http://docs.djangoproject.com/en/dev/ref/django-admin/#inspectdb
inspectdb
Introspects the database tables in the database pointed-to by the DATABASE_NAME setting and outputs a Django model module (a models.py file) to standard output.
Use this if you have a legacy database with which you'd like to use Django. The script will inspect the database and create a model for each table within it.
As you might expect, the created models will have an attribute for every field in the table.
If there are entirely different approaches to doing this with ArangoDB and javascript please point me in the right direction.
django-admin inspectdb [table [table ...]] targets relational databases where tables have schema and because of that it's possible to generate model
ArangoDB is NoSQL with schemaless collections with ability to store various JSON documents types and because of that you'll need to get schema per document type.
While using fullstack javascript approach you can put your model in js module and use it on both front and backend.
for us, most reliable and scalable approach is based on Typescript as master with following-ish workflow
turn JSON to TS via VS Code extension json2ts.com
then you can
generate JSON Schema via typescript-json-schema
generate UML diagram with tsviz
convert JSON Schema to joi with enjoi
generate forms from JSON schema (front-end framework specific)
Context
Hi! I made something like graphql but with just Sequelize. I mean, Sequelize query options are JSON objects so, the client could send the options directly (with correct sanitization).
What I have done
Just for curiosity, I built that, and it works just fine. Now my doubt is: how bad is that?
this is an example of the client using this API
const res = await http.post(APIs.FINDER, {
model: 'User',
options: {
where: {
id: someId
},
attributes: ['name', 'active']
},
include: [
{
as: 'zone',
attributes: ['name']
}
],
order: [['createdAt', 'DESC']]
});
nice right?
Sanitization/Constraints
About sanitization, I have to:
check that the includes have a known limit, eg.: no more than 10 nested includes
check that the params are not SQL strings or other hacks (Sequelize take care about that)
don't allow Sequelize functions, just simple queries
Questions
with that in mind, I think this could be used in production.
Have I missed something that could reject this idea from production usage? (security/usage/etc)
Have graphql some specific feature that makes me prefer it against this custom solution?
Would you use it in a production environment? I can't imagine why not
My thought to the questions:
I don't recommend this style of API. It will expose your backend implementation to the public which make you have difficulty dealing with every security conditions, not to mention the business logic and authorization. Also, it would be hard to improve your performance because the behavior is tightly coupled with the sequelize package.
You can consider this post: GraphQL Mutation Design: Anemic Mutations. A good GraphQL API should be driven by domain and requirement instead of be driven by data.
NO! I've experienced a hard time dealing with this api style.
Actually, this is not a good idea. If you are organizing an one-man full-stack project, it may seem fast in the first place, but the cost of development would skyrocket until you cannot move on. If you are working as a group, you can notice that the client side is tightly coupled with the server side, which is very bad for developing.
In the client side, it only need a finite set of apis instead of apis with infinite possibilities.
In the server side, you can do nothing but hand the data over to sequelize, which make it hard to improve your performance, to add logic layer and to introduce another database system like elastic search into your codebase.
When it comes to designing an API, you can consider Domain Driven Design which known as DDD. It's preferred to use GET Friends?limit=10 api than to use GET { type: 'User", where: ..., include: ..., order: ..., limit: 10 }
By the way, GraphQL is not just a query language, it is a thin API layer in essence (ref). So don't use it as a JSON database but treat it as an API which focuses on the business need.
For example, here is a User model:
{
"User": {
"id": 1,
"name": "Mary",
"age": 20,
"friendIds": [2, 3, 4]
}
}
But in GraphQL, based on what you need, it may become :
type User {
id: ID
name: String
friends: [User]
friendCount: Int
friendsOverAge18: [User]
}
You can read this great article about how to design a GraphQL API: Shopify/graphql-design-tutorial
I have two GraphQL schemas. One is written in Javascript and the other is written in Java.
Is there any way for me to combine the two into a single GraphQL implementation.
For example:
GraphQL Server A can query the following:
{
cats
}
GraphQL Server B can query the following:
{
dogs
}
I want my GraphQL Server to be able to query by somehow combining the two together
{
cats
dogs
}
I want to know if there is something that exists that does this already or if I have to do it myself. If I have to do it myself where should I start?
There are a few ways to do this, the term for it that the community has settled on is "schema stitching"
Apollo graphql-tools has a solution <-- I would start with this one
These guys have a solution
And I created a simple solution that I would not recommend using unless you have a really strong opinion and are willing to contribute to supporting it if I decided not to.
I'm trying to implement dynode to talk with dynamodb form a node.js script.
There are several examples on the Internet that shows how to do that with dynode, such as:
var opts = {read: 20, write: 25, hash: {name: String}, range: {age: Number}};
dynode.createTable("ExampleTable", opts, console.log);
which actually does the trick and works for me...
The issues I'm having is that I need to implement a shema on the same time when I create the database, or at least after that, a shema means that I need to tell the dynamodb to add a first_name field with string format, an address with string format etc...
there is no way nor instructions that shows how to do that ...
It's annoying to spend so much time on a so simple issue, because it is not well documented...
here is the dynode github web site:
Thanks
DynamoDB doesn't have schemas (if that's what you mean).
You can't force the table to represent a fixed set of attributes.
You can make sure in your application code that each item you store in the table will have the attributes you require, but the DynamoDB API won't enforce it.
Look here how to build your Item objects before putting them in db
Is there a javascript library that will allow me to express object predicates in a DSL similar to MongoDB's query language? For the sake of clarity in a large program, I'd like to be able to say:
var obj = {
a: 1,
b: 'abcdefg'
}, qry = {
a: { $gt: 0 },
b: /^abc/
};
if(query(qry).matches(obj)) {
// do something appropriate since
}
instead of:
var obj = {
a: 1,
b: 'abcdefg'
};
if(obj.a>0 && qry.b.test(obj.b)) {
// do something appropriate
}
I'm using Node.js, so anything on NPM would be great. It would be an added bonus if the library can select objects out of an array as well as just matching individual objects.
I reviewed these two related questions, but they weren't particularly helpful for my situation:
Implementing goMongoDB-like Query expression object evaluation
Evaluating MongoDB-like JSON Queries in PHP
OK I found the answer: Sift.js
Now for the long answer: This has been asked and answered before. The salient points are:
Use Sift if you really want Mongo syntax
If you want to be more mainstream, use Underscore.js like everyone else. It has heaps of handy functions in addition to the fact that it basically does what sift does with a slightly different syntax.
You may not need any library at all - modern browsers support many useful functions directly on the Array prototype, like filter() for example.
As a final note, mongodb-riff appears to be trying to do something similar but currently the page states clearly that it doesn't work - perhaps it's abandoned. But his readme is at least of value :-), he mentions sift and Query Engine which looks more mature, though too complicated for me!
Personally I'm going to go with Underscore because now that I've looked into it for the first time, I realise that it has heaps of handy stuff I need, plus I really only wanted to do simple functions like what would be _.find() in Underscore. But I guess if you want to do more complicated mongo-like queries, you'll do it in less LOC with Sift.
Check out Mingo
I implemented it after finding no suitable alternative.
It is still actively being developed but is usable. Test coverage is not complete.
Usable from both browser and nodejs
[Edit]
This library is now the most complete implementation of MongoDB's query language for the frontend.
https://github.com/mirek/node-json-criteria library does exactly that - evaluates criteria queries on JSON objects using MongoDB query format.
lodash.js
You want to use lodash.js. Its a drop in replacement for underscore.js.
The performance is twice as fast.
http://lodash.com/
The closest I could find was linq.js, which is LINQ for JavaScript. Hopefully this will be of some help to you.