Giter Site home page Giter Site logo

arangolite's People

Contributors

asmaloney avatar avesanen avatar bendikro avatar cuonglm avatar cyrilleverrier avatar hanemile avatar nvhbk16k53 avatar snocorp avatar solher avatar stephanwilliams 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

arangolite's Issues

Allow for extension of the library with change to Runnable

I've just started using your library in a project and I really like the API. I can definitely understand wanting to avoid creating an overly complex API as it makes it complicated to maintain and becomes a barrier to adoption.

My use case for Arango is a bit different than the original intent of arangolite in that I need to be able to create documents and perform a few other API calls. Instead of adding bloat to your library, I would like to propose a change to the Runnable interface to allow for extensions to be created instead.

The change would be to export the methods in Runnable as follows:

type Runnable interface {
    Description() string // Description shown in the logger
    Generate() []byte    // The body of the request
    Path() string        // The path where to send the request
    Method() string      // The HTTP method to use
}

This would require changing all the existing Runnables in your library but would then allow others to extend the library by simple creating new Runnable implementations and passing them to DB.Run.

Let me know if this would be acceptable and I can create a PR to make the changes.

Make db fields public

I trying to use this library as the basis for an ArangoDB migration tool. Creating a new database is harder than it should be since the DB properties are hidden. I'm sure I could get them with reflect, but I don't think that should be necessary. Would you be open to making the fields for NewDatabase public via an interface or just regular public?

How Do I Remove Edge

Is this even possible using AQL only?

From here it says that currently there is no way to do this via AQL. But arangolite doesn't seems to have a way to remove edge using graph management interface?

Accessing error code from returned error

When performing a CreateDatabase where the database already exists, the database returns error code 1207 (https://docs.arangodb.com/3.0/Manual/Appendix/ErrorCodes.html, ERROR_ARANGO_DUPLICATE_NAME).

This error code is wrapped in a numberedError at https://github.com/solher/arangolite/blob/v2.0.1/database.go#L207

However, at the next step, the numberedError is wrapped in a statusCodedError at https://github.com/solher/arangolite/blob/v2.0.1/database.go#L213

The statusCodedError is what is returned by Send.

My question is how should the error code be accessed?

HasErrorNum will not work, since it requires a numberedError as input, and casting to statusCodedError to access the error attribute doesn't work, since statusCodedError is not exported.

Current result of arangolite.HasStatusCode(err) is 409, but arangolite.HasErrorNum(e_status, 1207) gives false.

Unmarshalling Result Has Duplicate Methods

Response unmarshalling requires wrapping the unmarshalled interface in a result tag.

`json"result"`

I believe this is because both the Unmarshal and UnmarshalResult methods are both operating on the raw response which is enclosed in a result tag.

func (r *response) Unmarshal(v interface{}) error {
	if err := json.Unmarshal(r.raw, v); err != nil {
		return errors.Wrap(err, "response unmarshalling failed")
	}
	return nil
}

func (r *response) UnmarshalResult(v interface{}) error {
	if err := json.Unmarshal(r.raw, v); err != nil {
		return errors.Wrap(err, "response result unmarshalling failed")
	}
	return nil
}

I believe UnmarshalResult should be operating on the parsedResponse instead.

Quote in json value breaks the queries

Hi Fabien

When inserting a struct represeting a user, if any field of this user contains a simple quote, the resulting AQL query is invalid:

My code is the following one

userJsonBytes, err := json.Marshal(user)
	if err != nil {
		return err
	}
	userJson := string(userJsonBytes)

	query := requests.NewAQL(` UPSERT { "id":"%s" } INSERT %s UPDATE %s IN %s `, user.ID, userJson, userJson, CollectionName)

I probably could find a workaround by creating a dedicated json marshaller; but shouldn't the driver prevent this issue?

Support 3.x

The API changed between the version. For example Collects returns "results". The current library can't read that.

Prevent AQL injection in transaction

To prevent AQL injection in transaction, my understanding of the documentation is that we could use javascript variables.

I created a modified version of transaction.

Its usage:

transaction := arangolite.NewTransaction([]string{}, []string{}).
    AddQuery("var1", "FOR d IN nodes FILTER d._key == {{.key}} RETURN d").
    AddQuery("var2", "FOR d IN nodes FILTER d._id == {{.var1}}._id RETURN d.key").Return("var2")

transaction.Bind("key", 123)

result, err := db.Run(transaction) 

But the result is not what I expect; It returns an empty array instead of [123].
The reason is that the replacement of var1 in the second query is not working.

Do you have any idea to fix this?

BTW, this solution does not seem to work with collection names. It looks like they cannot by defined by a javascript variable. But I assume that's a minor limitation.

Possibility to get []byte instead of umarshaled struct as result

We are using this lib and extracting large chunks of json. The problem is that these jsons does not have strict structure so they should be unmarshaled only to map[string]interface{} for latter use, but in our scenario we do not need to unmarshal json at all and raw []byte of json is ok. It would be nice:

  • To have func (db *Database) GetRaw(ctx context.Context, q Runnable) (json.RawMessage, error) or equivalent.

Or

  • Make followCursor as exported so this can be easily achieved with Send.

Any opinions?

Support cursors without goroutines

Creating something like pagination seems expensive with this way.

Say I run a query like FOR n IN nodes LIMIT 1000 RETURN 20, by using Run, all 1000 results if found in the DB are returned, and no cursor key to manage the request.

Using RunAsync means having a goroutine followCursor created everytime there is more results in the cursor, and I am forced to get everything by checking if there is more just not to have hanging goroutine(s) in the background, or close the channel(meaning I have to begin going through the cursor again).

If I had multiple clients in an application running the same query, I have to keep these goroutines even though none of them might be interested in going through the list of results.

I propose we return the result.ID and let the user(developer) decide a proper method for getting the results.

Requests produce no result

When running the example below (derived from the readme example), I have two problems:

  • The node collection is not created.
  • the async request returns an empty array
package main

import (
  "encoding/json"
  "fmt"

  "github.com/solher/arangolite"
)

type Node struct {
  arangolite.Document
}

type MyNode struct {
  // The document handle. Format: ':collection/:key'
  ID string `json:"_id,omitempty"`
  // The document's revision token. Changes at each update.
  Rev string `json:"_rev,omitempty"`
  // The document's unique key.
  Key string `json:"_key,omitempty"`
}

func main() {
  db := arangolite.New().
    LoggerOptions(false, false, false).
    Connect("http://localhost:8529", "_system", "root", "")

  db.Run(&arangolite.CreateDatabase{
        Name: "testDB",
        Users: []map[string]interface{}{
            {"username": "root", "passwd": ""},
            {"username": "user", "passwd": ""},
        },
    })
  db.SwitchDatabase("testDB").SwitchUser("user", "")

  db.Run(&arangolite.CreateCollection{Name: "nodes"})

  // The Run method returns all the query results of every batches
  // available in the cursor as a slice of byte.
  key1 := "48765564346"
  key2 := "48765564347"

  _, err := remove(db, key1)
  _, err = remove(db, key2)

  _, err = insert(db, key1)
  _, err = insert(db, key2)

  if (err != nil) {
    return
  }

  q := arangolite.NewQuery(`
    FOR n
    IN nodes
    FILTER n._key == "%s"
    LIMIT 1
    RETURN n
  `, key1)

  async, asyncErr := db.RunAsync(q)

  if(asyncErr != nil){
    fmt.Printf("asyncErr %v", asyncErr)
  }

  nodes := []Node{}
  decoder := json.NewDecoder(async.Buffer())

  for async.HasMore() {
    batch := []Node{}
    decoder.Decode(batch)
    fmt.Printf("%v", decoder)
    nodes = append(nodes, batch...)
  }

  fmt.Printf("%v", nodes)
}

func remove(db *arangolite.DB, key string) ([]byte, error) {
  removeQuery := arangolite.NewQuery(`
      REMOVE  { _key: '%s' }  IN nodes
    `, key)
  res, err := db.Run(removeQuery)
  if(err != nil) {
    fmt.Printf("Remove error %v", err)
  }
  return res, err
}

func insert(db *arangolite.DB, key string) ([]byte, error) {

  node := MyNode{
     ID: "nodes/" + key,
     Rev: key,
     Key: key,
  }

  value, marshallErr := json.Marshal(node)
  if(marshallErr != nil) {
    fmt.Printf("Insertion error %v. Cannot convert %v to JSON", marshallErr, value)
    return nil, marshallErr
  }
  insertQuery := arangolite.NewQuery(`
      INSERT %s
      IN nodes
    `, value)

  insertResult, err := db.Run(insertQuery)

  if (err != nil) {
    fmt.Printf("Insertion error %v", err)
  }
  return insertResult, err
}

What did I get wrong?

database.Run() response result (parsedResponse.Result) always empty

The response object returned by database.Send()
is passed to database.followCursor() in the database.Run() function.

When the response object is created in senders.Send(), the response's parsed (parsedResponse) attribute is unmarshalled.

It seem the parsedResponse.Result attribute is never populated, and is simply an empty array.

The problem then occurs in database.followCursor() where the call to r.RawResult() always returns an empty array, and hence, the result is not unmarshalled into the v input argument.

I'm I doing something wrong?

Basic example error

Hi

In the basic example, in the readme, I believe you should switch these 2 lines:

_, _ := db.Run(&arangolite.CreateCollection{Name: "nodes"})

db.SwitchDatabase("testDB").SwitchUser("user", "password")

Otherwise you create the collection in the wrong database

Add support for jwt

The new http api has a jwt auth method, it would be cool to add it. ๐Ÿ˜„

Adding new commands

I will extend the driver. I already started with an edge creation feature. But something worries me: in your readme you suggest to add everything in requests.go. So this file could become very long...
I believe the code should be organised by around the business domain, and not the technical notions. By example the create edge request definition should be in edge.go.
Do you agree with this?

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.