Giter Site home page Giter Site logo

arango's Introduction

aranGO

go get github.com/diegogub/aranGO

Golang driver for ArangoDB.

Here are the things you can do until now:

  • Databases : create
  • Collections : drop, create, list, truncate
  • Documents : save, replace,patch, query (simple query,AQL,Transactions)
  • Edges : Relate documents, save, patch, replace
  • Execute transactions
  • Execute AQL
  • Replication config

Additional Features

Any ideas for the driver or bug fixes please feel free to create a issue or pull-request to dev :)

Documentation

https://gowalker.org/github.com/diegogub/aranGO

Basic Usage

import ara "github.com/diegogub/aranGO"

type DocTest struct {
  ara.Document // Must include arango Document in every struct you want to save id, key, rev after saving it
  Name     string
  Age      int
  Likes    []string
}

Connect and create collections

    //change false to true if you want to see every http request
    //Connect(host, user, password string, log bool) (*Session, error) {
    s,err := ara.Connect("http://localhost:8529","diego","test",false) 
    if err != nil{
        panic(err)
    }

    // CreateDB(name string,users []User) error
    s.CreateDB("test",nil)

    // create Collections test if exist
    if !s.DB("test").ColExist("docs1"){
        // CollectionOptions has much more options, here we just define name , sync
        docs1 := NewCollectionOptions("docs1",true)
        s.DB("test").CreateCollection(docs1)
    }

    if !s.DB("test").ColExist("docs2"){
        docs2 := NewCollectionOptions("docs2",true)
        s.DB("test").CreateCollection(docs2)
    }

    if !s.DB("test").ColExist("ed"){
        edges := NewCollectionOptions("ed",true)
        edges.IsEdge() // set to Edge
        s.DB("test").CreateCollection(edges)
    }

Create and Relate documents

  var d1,d2 DocTest
  d1.Name = "Diego"
  d1.Age = 22
  d1.Likes = []string { "arangodb", "golang", "linux" }
  
  d2.Name = "Facundo"
  d2.Age = 25
  d2.Likes = []string { "php", "linux", "python" }


  err =s.DB("test").Col("docs1").Save(&d1)
  err =s.DB("test").Col("docs1").Save(&d2)
  if err != nil {
    panic(err)
  }

  // could also check error in document
  /*
  if d1.Error {
    panic(d1.Message)
  }
  */

  // update document
  d1.Age = 23
  err =s.DB("test").Col("docs1").Replace(d1.Key,d1)
  if err != nil {
    panic(err)
  }
  
  // Relate documents
  s.DB("test").Col("ed").Relate(d1.Id,d2.Id,map[string]interface{}{ "is" : "friend" })

AQL

// query query 
  q := ara.NewQuery("FOR i in docs1 RETURN i")
  c ,err:=s.DB("test").Execute(q)
  if err != nil {
    panic(err)
  }
  var doc DocTest

  for c.FetchOne(&doc){
    log.Println(doc)
  }

Transactions

// saving document with transaction
func TranSave(db *ara.Database,doc interface{},col string,counter string) (*ara.Transaction,error){
  if  col == "" || counter == ""{
    return nil,errors.New("Collection or counter must not be nil")
  }

  write := []string { col }
  q := `function(params){
                var db = require('internal').db;
                try {
                  var c = db.`+col+`.document('c');
                }catch(error){
                  var tmp = db.`+col+`.save( { '_key' : 'c' , '`+counter+`' : 0 });
                }
                var c = db.`+col+`.document('c');
                var co = c.`+counter+` || 0;
                co = co + 1 ;
                // update counter
                db.`+col+`.update(c, { '`+counter+`' : co }) ;
                params.doc.s = -1 * co ;
                params.doc.created = new Date().toISOString();
                var res = db.`+col+`.save(params.doc) ;
                return res._key
        }
  `
  t := ara.NewTransaction(q,write,nil)
  t.Params = map[string]interface{}{ "doc" : doc }

  err := t.Execute(db)

  return t,err
}

Models

To be a model, any struct must implement Modeler Interface.

type Modeler interface {
    // Returns current model key
    GetKey() string
    // Returns collection where I should save the model
    GetCollection() string
    // Error
    GetError() (string, bool)
}

Implement Modeler and add tags to struct..

type DocTest struct {
  ara.Document // Must include arango Document in every struct you want to save id, key, rev after saving it
// required tag for strings.
  Name     string `required:"-"`
// unique tag validate within collection users, if username is unique
  Username string `unique:"users"`
// enum tag checks string value
  Type     string `enum:"A,M,S"`
// Next release I will be implementing some other tags to validate int
and arrays
  Age      int
  Likes    []string
}

func (d *DocTest) GetKey() string{
  return d.Key
}

func (d *DocTest) GetCollection() string {
  return "testcollection"
}

func (d *DocTest) GetError()(string,error){
    // default error bool and messages. Could be any kind of error
    return d.Message,d.Error
}

// pass ArangoDB database as context
ctx, err :=  NewContext(db)

// save model, returns map of errors or empty map
e := ctx.Save(d1)

// check errors, also Error is saved in Context struct
if len(e) > 1 {
  panic(e)
}

// get other document
d2.Key = "d2key"
ctx.Get(d2)
log.Println(d2)

We can implement hooks to execute when saving,updating or deleting model..

// execute before saving
func (d *DocTest) PreSave(c *ara.Context) {
   var e error
  // Any extra validation
  // ......
  // ......
  if e != nil {
    // errors should be set into context struct
    c.Err["presave"] = "failed to validate doctest"
  }

  return
}

arango's People

Contributors

abijr avatar admarcel avatar codelingobot avatar cugu avatar diegogub avatar gregzuro avatar jurrian avatar qgymje avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

arango's Issues

DB - fails to initialize existing collections - end up with duplicate error

db.ColExist("colname") returns false on each run - but attempt to create leads to error and blocks.

Session.DB -> intends to loadCollection into Database through the call Collections(&db) which is defined in collections.go

    res, err = db.get("collection?excludeSystem=true", "", "GET", nil, db, db)

This call works well but db does not get initialized with expected Collections due to missing tag for json decoding.

The fix below worked.

type Database struct {
    Name        string `json:"name"`
    Id          string `json:"id"`
    Path        string `json:"path"`
    System      bool   `json:"isSystem"`
    Collections []Collection `json:"result"` // FIX
    sess        *Session
    baseURL     string
}

Tried to create a document but it blocks

I copied the example code at README and modified it.
However when I ran my code, it prints "createAndRelateDocs start" then it blocks at
https://github.com/hnakamur/arangodb_experiment/blob/fc8adf425f94fd1487108da7f1a77e4122f58f21/cmd/example1/main.go#L106-L107

I waited a minute or so, and I gave up.
Could you tell me how to fix the problem?

I user the root user to connect to the database.

My environments:

Cannot use this library at all

Hi, I wanted to use your library but something is failing, github.com/diegogub/napping is not found.

	github.com/diegogub/aranGO imports
	github.com/diegogub/napping: cannot find module providing package github.com/diegogub/napping: module github.com/diegogub/napping

Problem with FetchOne

We found strange problem with FetchOne when using LIMIT in query.
Code:

        ...
    q := ara.NewQuery("FOR i IN cities LIMIT 0,5 RETURN i")
    c, err := adb.DB("test").Execute(q)
    if err != nil {
        log.Fatalf("%s", err)
    }
    if c.Err {
        log.Fatalf("error %s\n", c.ErrMsg)
    }
    var doc City
    for c.FetchOne(&doc) {
        log.Printf("%#v", doc)
    }

It prints only first 4 items, because in cursor.go handling of Index and max in FetchOne is not correct.
We didn't test, but code in FetchBatch looks like it has same problem.
By looking in cursor.go - this would happen without limit too, last result would not be printed.

unique constraint violated error not returned on save

error is nill on result of save when 409 returned from arangodb

Case needed in
func (col *Collection) Save(doc interface{}) error {
...
case 409:
return errors.New( "unique constraint violated" )

To reproduce, add a unique index on a collection.
Call to add a document multiple times, the error is returned by Arango but not by the save function.

I believe this should be added to other functions as well.

Total item count

How could I get the total number of items when I get a subset using the limit parameter?
The fullcount property is always 0, event when the AQL request contains a "LIMIT" clause.

Do you have plan to add testcase each file?

aql2.go         aql2_test.go         cursor.go    cursor_test.go
graph.go      graph_test.go      replication.go  replication_test.go
....

If yes, I will add testcase and p/r. ๐Ÿ˜Š

or
Do you have a problem when add testcase each file?

I'm learning Go and studying ArangoDB, so interested in aranGo project.

Support for Go Modules

Adding support for Go Modules.

Got this error, when initializing Go Modules.

        github.com/diegogub/napping: cannot find module providing package github.com/diegogub/napping: module github.com/diegogub/napping: git ls-remote -q origin in /home/arwego/go/pkg/mod/cache/vcs/6565de94fe36382a71c94076fec7772ac692d61c89fe5129d9e446a2efc0ba65: exit status 128:
        ERROR: Repository not found.
        fatal: Could not read from remote repository.

        Please make sure you have the correct access rights
        and the repository exists.

Replace is not Update

I miss Update-Function! Replace must have all the data, update can also single value and does not consider the other values. With several objects in a collection is unproductive. With all due respect!

// update document d1.Age = 23 err =s.DB("test").Col("docs1").**Replace**(d1.Key,d1) if err != nil { panic(err) }

How about adding (s *Session) Errors() []error?

I noticed an error is ignored in (db Database) Col(name string) *Collection at

db.CreateCollection(&col)

However if we change the signature to (db Database) Col(name string) (*Collection, error), it's harder to use.

So, how about adding (s *Session) Errors() []error?
For example, gorm (which is an object-relational mapping library) has the following methods:

Tags : infinite loop

Let me know if i'm wrong :

func getTags(obj reflect.Type, tags map[string]string, key string) {

    if obj.Kind() != reflect.Struct && obj.Kind() != reflect.Ptr {
        return
    }

    var tag string

    fieldsCount := obj.NumField()

    for i := 0; i < fieldsCount; i++ {
        structField := obj.Field(i)
        if structField.Anonymous && structField.Type.Kind() == reflect.Struct {
            getTags(obj, tags, key)
        } else {
            tag = structField.Tag.Get(key)
            if tag != "" {
                tags[structField.Name] = tag
            }
        }
    }
}

So if it's another struct, it will call itself with the same tag (obj)

Result in a infinite loop (overflow)

Possible solution: replaced with structField.Type

getTags(structField.Type, tags, key)

=== Step to reproduce ===

In a model

type Model struct {
    aranGO.Document
}

type Event struct {
    Model
    Title string        `json:"title"`
}

The embedded struct should cause the SO

AvailableDBs() always outputs []

AvailableDBs() always outputs [].

s, err := aranGO.Connect("http://localhost:8529", "root", "", false)
dbs, err := s.AvailableDBs()
fmt.Println(dbs)

Question: Reusing Collection

Is it OK to define a collection variable once (like col := s.DB("sample-db").Col("sample")) and reuse it (from a single goroutine, no concurrent access)?

Instead of calling s.DB("sample-db").Col("sample") every time?

  • If so, it would be helpful to change front page samples, this way.

Find a way to wrap the ArangoDB transaction system

Following the issue #19.

I tried to write a wrapper at first. But what is hard to do is to wrap the processing you need to do between the two operations.

An example in my case. I need to abstract a create operation: a call to my Create API method creates the nodes but also the edges linking them to their owner user.

So I need a transaction executing:

FOR n IN [{"name":"foo"}, {"name":"bar"}]
INSERT n IN nodes
RETURN NEW

// RETURNS:
// [
//   {
//     "_id": "nodes/47473545749",
//     "_rev": "47473545749",
//     "_key": "47473545749",
//     "name": "foo"
//   },
//   {
//     "_id": "nodes/47472824853",
//     "_rev": "47472824853",
//     "_key": "47472824853",
//     "name": "bar"
//   }
// ]

Then:

FOR l IN [{"_from": "users/5768765876", "_to": "nodes/47473545749"}, {"_from": "users/5768765876", "_to": "nodes/47472824853"}]
INSERT l IN links

How can we do the processing to convert the array of nodes to the array of links between the two requests, without writing Javascript in the transaction ?

Maybe just writing AQL again I suppose...

 FOR n IN [
   {
     "_id": "nodes/47473545749",
     "_rev": "47473545749",
     "_key": "47473545749",
     "name": "foo"
   },
   {
     "_id": "nodes/47472824853",
     "_rev": "47472824853",
     "_key": "47472824853",
     "name": "bar"
   }
 ]
 RETURN {"_from": "users/5768765876", "_to": n._id}

And then links the three queries in JS. Haha why not ?

Cannot create graph

I am trying to create a graph but have some problems. I set log to true and got these error

  • The first error : orrrorphanCollections should be an array.
    • I fixed it by defineng orphanCollections to an empty array []string{}
  • The second error : cannot use _key
    • I fixed it by adding "omitempty" to key

My code is like following

    //Connect(host, user, password string, log bool) (*Session, error) {
   s,err := ara.Connect("http://localhost:8529","root","root",true) 
   s.CreateDB("test",nil)
   docs1 := NewCollectionOptions("docs1",true)
   s.DB("test").CreateCollection(docs1)
   
  var d1,d2 DocTest
  d1.Name = "Diego"
  d1.Age = 22
  d1.Likes = []string { "arangodb", "golang", "linux" }
  
  d2.Name = "Facundo"
  d2.Age = 25
  d2.Likes = []string { "php", "linux", "python" }

  err =s.DB("test").Col("docs1").Save(&d1)
  err =s.DB("test").Col("docs1").Save(&d2)
  if err != nil {
    panic(err)
  }

  // could also check error in document
 
  // update document
  d1.Age = 23
  err =s.DB("test").Col("docs1").Replace(d1.Key,d1)
  if err != nil {
    panic(err)
  }

  // Relate documents
  s.DB("test").Col("ed").Relate(d1.Id,d2.Id,map[string]interface{}{ "is" : "friend" })

Put the JSON2AQL filter feature in a separate package

Hi,
I'm currently writing my own lightweight ArangoDB driver. Just 50 lines to run raw AQL because I don't need all the ORM-like features.
I love your JSON2AQL feature (as I wrote the same thing for SQL) and I'd like to use it in my package.
Could you move the feature in a separate package (or more easily inside a subpackage) ? I will pull request to help you write tests if you want.

I will use it like that:

func AQLFilter(json string) string {
    return aranGO.FilterJSON(json).Generate()
}

Thanks for your work !

Cannot retrieve documents

I'm able to save new documents and patch them, but I'm not being able to retrieve the documents.
If I do this:

var user User
dbase, _ := aranGO.Connect("http://localhost:8529", "", "", false)
b := dbase.DB("kails").Col("users")
b.Any(user)

log.Println(user)

It just prints an empty User (default values). And I do have documents in the collection. Do I need to add credentials for the database?

Apparently, Any requires to send the collection name on the payload and aranGO isn't sending it. I might start a pull request with a fix for this (First, Example are also affected).

Connecting to a database other than _system

I was unable to find an answer to this anywhere in the documentation.

The Connect function connects to the default _system database and allows you to run queries on any database from there.

I would prefer to connect with a user that does not have access to _system and use a database other than _system. How do I specify which database to connect to?

If this is not possible, perhaps it should be. It seems dangerous to only allow users to connect who have _system access.

Set DATE to Database

How I get the date in my DB?

sav.Date_now = `DATE_ISO8601(DATE_NOW())`
err := db.Col("collection").Save(&sav)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.