diff --git a/README.md b/README.md index 3804e06..40c52e5 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,16 @@ of new features. * Support for [GeoJson](http://geojson.org/) indexes. * Support for GridFS + +### todo, version 1. + +* ajouter liens de remerciment +* être capable de voir la carte avec l'image +* meilleur légende d'histogram +* Ajouter filtre à histogram +* Ajouter filtre à carte +* Être capable de chercher par objectId etc. + ### screenshots ![general view](https://bytebucket.org/damyot/vulture/raw/default/screenshots/screenshot_1.png) diff --git a/api.go b/api.go index 778b309..0a0e420 100644 --- a/api.go +++ b/api.go @@ -4,6 +4,7 @@ import ( "bitbucket.org/damyot/vulture/shared" "encoding/json" "errors" + "fmt" "github.com/gorilla/mux" "labix.org/v2/mgo" "labix.org/v2/mgo/bson" @@ -89,7 +90,7 @@ func (this *VultureBackend) getIndexes() (interface{}, error) { } ret := make([]map[string]interface{}, len(idxs)) for i, idx := range idxs { - ret[i] = map[string]interface{}{"name": idx.Name, "keys": idx.Key} + ret[i] = map[string]interface{}{"name": idx.Name, "keys": idx.Key, "unique": idx.Unique} } return ret, nil @@ -131,9 +132,11 @@ func (this *VultureBackend) wrapDocumentWithMetadata(doc interface{}, query *mgo return ret, nil } -func (this *VultureBackend) GetStat(key string) (interface{}, error) { +func (this *VultureBackend) GetStat(query bson.M, key string) (interface{}, error) { s := NewStatAggregator() - query := bson.M{key: bson.M{"$exists": true}} + if _, ok := query[key]; !ok { + query[key] = bson.M{"$exists": true} + } iter := this.Collection.Find(query).Select(bson.M{key: 1}).Iter() result := make(map[string]interface{}) @@ -158,9 +161,11 @@ func (this *VultureBackend) GetStat(key string) (interface{}, error) { return <-out, nil } -func (this *VultureBackend) GetHistogram(key string, min, max float64, numberOfBins int) (interface{}, error) { +func (this *VultureBackend) GetHistogram(query bson.M, key string, min, max float64, numberOfBins int) (interface{}, error) { hm := &HistogramMaker{min, max, numberOfBins} - query := bson.M{key: bson.M{"$exists": true}} + if _, ok := query[key]; !ok { + query[key] = bson.M{"$exists": true} + } iter := this.Collection.Find(query).Select(bson.M{key: 1}).Iter() result := make(map[string]interface{}) @@ -248,7 +253,7 @@ func getAllDocuments(w http.ResponseWriter, request *http.Request) (interface{}, if !ok || queryString == "" { return vb.GetAllDocuments(nil) } - query := make(map[string]interface{}) + query := make(bson.M) if err := json.Unmarshal([]byte(queryString), &query); err != nil { return nil, errors.New("invalid json") } @@ -302,12 +307,22 @@ func getStats(w http.ResponseWriter, request *http.Request) (interface{}, error) return nil, err } + queryString, ok := mux.Vars(request)["query"] + query := make(map[string]interface{}) + if ok && queryString != "" { + err := json.Unmarshal([]byte(queryString), &query) + if err != nil { + return nil, errors.New("invalid json") + } + } + fmt.Println(">>>", queryString) + vars := mux.Vars(request) key, ok := vars["key"] if !ok { return nil, errors.New("key field not specified") } - return vb.GetStat(key) + return vb.GetStat(query, key) } func getHistogram(w http.ResponseWriter, request *http.Request) (interface{}, error) { @@ -344,6 +359,14 @@ func getHistogram(w http.ResponseWriter, request *http.Request) (interface{}, er return nil, errors.New("key field not specified") } - return vb.GetHistogram(key, min, max, numberOfBins) + queryString, ok := vars["query"] + query := make(map[string]interface{}) + if ok && queryString != "" { + err := json.Unmarshal([]byte(queryString), &query) + if err != nil { + return nil, errors.New("invalid json") + } + } + return vb.GetHistogram(query, key, min, max, numberOfBins) } diff --git a/client/coffee/controllers/geojsonmapCtrl.coffee b/client/coffee/controllers/geojsonmapCtrl.coffee index e5039ca..8247342 100644 --- a/client/coffee/controllers/geojsonmapCtrl.coffee +++ b/client/coffee/controllers/geojsonmapCtrl.coffee @@ -49,6 +49,7 @@ root.controllers.controller('geojsonmapCtrl', ['$scope', '$routeParams', '$locat $scope.geojsonData = {} $scope.idx = Number($routeParams.idx) $scope.center = getLocalStorageCenter() + $scope.queryObject = $routeParams.query or "{}" $scope.$watch 'center', () -> localStorage.setItem("mapCenter", JSON.stringify($scope.center)) @@ -113,5 +114,11 @@ root.controllers.controller('geojsonmapCtrl', ['$scope', '$routeParams', '$locat else $scope.mode = 'all' $scope.initAllDocuments() + + $scope.changeQuery = (query) -> + if query == "" + return "" + r = $routeParams + $location.path "/#{ r.server }/#{ r.database }/#{ r.collection }/idx/1/query/#{query}/geojson/#{r.key}" ]) diff --git a/client/coffee/controllers/keyStatCtrl.coffee b/client/coffee/controllers/keyStatCtrl.coffee index ecca1e1..a09e145 100644 --- a/client/coffee/controllers/keyStatCtrl.coffee +++ b/client/coffee/controllers/keyStatCtrl.coffee @@ -19,11 +19,12 @@ findHistogramMax = (stats) -> getAxisLabel = (min, stepSize, numberOfBins) -> return (min + 0.5 * stepSize + i * stepSize for i in [0... numberOfBins]) -root.controllers.controller('keyStatCtrl', ['$scope', '$routeParams', 'util', ($scope, $routeParams, util) -> +root.controllers.controller('keyStatCtrl', ['$scope', '$routeParams', '$location', 'util', ($scope, $routeParams, $location, util) -> $scope.name = $routeParams.key $scope.stats = [] - - base_url = "/api/#{ $routeParams.server }/#{ $routeParams.database }/#{ $routeParams.collection }" + $scope.queryObject = $routeParams.query or '{}' + + base_url = "/api/#{ $routeParams.server }/#{ $routeParams.database }/#{ $routeParams.collection }/query/#{$scope.queryObject}" stat_url = "#{ base_url }/stats/#{$routeParams.key}" $scope.alert=alert @@ -47,6 +48,12 @@ root.controllers.controller('keyStatCtrl', ['$scope', '$routeParams', 'util', ($ name: $routeParams.key color: '#008CBA' }] + + $scope.changeQuery = (query) -> + if query == "" + return "" + r = $routeParams + $location.path "/#{ r.server }/#{ r.database }/#{ r.collection }/stats/#{ r.key }/query/#{query}" util.get(stat_url).then((res) -> diff --git a/client/coffee/directives/key.coffee b/client/coffee/directives/key.coffee index 827f426..b5d1976 100644 --- a/client/coffee/directives/key.coffee +++ b/client/coffee/directives/key.coffee @@ -5,6 +5,12 @@ hasIndex = (keyName, indexes) -> return true return false +hasUniqueIndex = (keyName, indexes) -> + for index in indexes + if _.indexOf(index.keys, keyName) != -1 + return index.unique + return false + hasIndexAsc = (keyName, indexes) -> hasIndex(keyName, indexes) @@ -17,7 +23,10 @@ has2dIndex = (keyName, indexes) -> getStatsUrl = (keyName, routeParams)-> r = routeParams - "#/#{r.server}/#{r.database}/#{r.collection}/stats/#{ keyName }" + ret = "#/#{r.server}/#{r.database}/#{r.collection}/stats/#{ keyName }" + if r.query + ret = "#{ ret }/query/#{ r.query }" + return ret directive = () -> directive = @@ -34,6 +43,7 @@ directive = () -> $scope.statsUrl = getStatsUrl($scope.keyName, $routeParams) $scope.hasIndexDesc = hasIndexDesc($scope.keyName, $scope.indexes) $scope.hasIndexAsc = hasIndexAsc($scope.keyName, $scope.indexes) + $scope.isIndexUnique = hasUniqueIndex($scope.keyName, $scope.indexes) $scope.has2DIndex = has2dIndex($scope.keyName, $scope.indexes) $scope.showTools = false $scope.hasIndex = $scope.hasIndexDown or $scope.hasIndexUp or $scope.has2DIndex diff --git a/client/coffee/vultureApp.coffee b/client/coffee/vultureApp.coffee index a875f40..78545fb 100644 --- a/client/coffee/vultureApp.coffee +++ b/client/coffee/vultureApp.coffee @@ -21,6 +21,7 @@ config(['$routeProvider', ($routeProvider) -> $routeProvider.when('/:server/:database/:collection/_id/:id/field/:field', {templateUrl: 'partials/field.html', controller: 'fieldCtrl'}) $routeProvider.when('/:server/:database/:collection/idx/:idx', {templateUrl: 'partials/document.html', controller: 'documentCtrl'}) $routeProvider.when('/:server/:database/:collection/stats/:key', {templateUrl: 'partials/keyStat.html', controller: 'keyStatCtrl'}) + $routeProvider.when('/:server/:database/:collection/stats/:key/query/:query', {templateUrl: 'partials/keyStat.html', controller: 'keyStatCtrl'}) $routeProvider.when('/:server/:database/:collection/idx/:idx/query/:query', {templateUrl: 'partials/document.html', controller: 'documentCtrl'}) $routeProvider.when('/:server/:database/:collection/idx/all/geojson/:key', {templateUrl: 'partials/geojsonmap.html', controller: 'geojsonmapCtrl'}) $routeProvider.when('/:server/:database/:collection/idx/:idx/geojson/:key', {templateUrl: 'partials/geojsonmap.html', controller: 'geojsonmapCtrl'}) diff --git a/client/partials/directives/key.html b/client/partials/directives/key.html index bbe9b02..0418c67 100644 --- a/client/partials/directives/key.html +++ b/client/partials/directives/key.html @@ -1,13 +1,12 @@ {{keyName}} - - - - - - - - + + + + ∃! + + + \ No newline at end of file diff --git a/client/partials/directives/searchBar.html b/client/partials/directives/searchBar.html index c7fd6e2..e961444 100644 --- a/client/partials/directives/searchBar.html +++ b/client/partials/directives/searchBar.html @@ -1,7 +1,7 @@
- +
    diff --git a/client/partials/document.html b/client/partials/document.html index d202ff6..56610c7 100644 --- a/client/partials/document.html +++ b/client/partials/document.html @@ -4,7 +4,7 @@
    - {{idx}} / {{ meta.count || 0 | number | replaceAllCommasBySpaces }} + {{idx}} / {{ meta.count + idx - 1 || 0 | number | replaceAllCommasBySpaces }}
    diff --git a/client/partials/geojsonmap.html b/client/partials/geojsonmap.html index 9cafcc2..b988067 100644 --- a/client/partials/geojsonmap.html +++ b/client/partials/geojsonmap.html @@ -1,14 +1,17 @@ + + +
    - {{idx}} / {{ meta.count }} + {{idx}} / {{ meta.count + idx - 1}}
    - Showing a data set of {{geojsonData.data.geometries.length}} datum. + Showing {{meta.count}} documents on the same map.
    diff --git a/client/partials/keyStat.html b/client/partials/keyStat.html index d3cd505..36a0173 100644 --- a/client/partials/keyStat.html +++ b/client/partials/keyStat.html @@ -1,5 +1,5 @@ - +
    @@ -13,5 +13,5 @@
    - +
    \ No newline at end of file diff --git a/main.go b/main.go index 271a815..3fb2160 100644 --- a/main.go +++ b/main.go @@ -91,8 +91,8 @@ func serveApi(router *mux.Router) { router.Handle("/{server}/{database}/collections", ApiHandler(getAvailableCollections)) router.Handle("/{server}/{database}/{collection}/idx/{index:[0-9]+}", ApiHandler(getDocumentByIndex)) router.Handle("/{server}/{database}/{collection}/_id/{id}", ApiHandler(getDocumentById)) - router.Handle("/{server}/{database}/{collection}/stats/{key}", ApiHandler(getStats)) - router.Handle("/{server}/{database}/{collection}/histogram/{key}/{min}/{max}/{number_of_bins}", ApiHandler(getHistogram)) + router.Handle("/{server}/{database}/{collection}/query/{query}/stats/{key}", ApiHandler(getStats)) + router.Handle("/{server}/{database}/{collection}/query/{query}/histogram/{key}/{min}/{max}/{number_of_bins}", ApiHandler(getHistogram)) router.Handle("/{server}/{database}/{collection}/all", ApiHandler(getAllDocuments)) router.Handle("/{server}/{database}/{collection}/query/{query}/idx/{index:[0-9]+}", ApiHandler(getDocumentByQueryAndIndex)) router.Handle("/{server}/{database}/{collection}/query/{query}/all", ApiHandler(getAllDocuments)) diff --git a/params.yml b/params.yml index 88339d4..37a40ca 100644 --- a/params.yml +++ b/params.yml @@ -7,9 +7,9 @@ # The port where the service will run Port: 8000 -# The address where the service will run. If you wish to run it on your computer, you -# should use `localhost`. If you wish to share the service on your local network, you -# should use `0.0.0.0` +# The address where the service will run. If you wish to run it on your +# computer, you should use `localhost`. If you wish to share the service +# on your local network, you should use `0.0.0.0` ServingAddress: 0.0.0.0 # The list of mongo servers. Each server is an object with a field *name* that will diff --git a/stats.go b/stats.go index 6a12d8b..9ae2445 100644 --- a/stats.go +++ b/stats.go @@ -45,7 +45,7 @@ func (this *HistogramMaker) MakeHistogram(dataChannel chan float64, outputChanne } i := this.findSuitableBinForDatum(this.Min, step, datum) if i >= len(hist) || i < 0 { - log.Println("what the fuck?!", this.Min, step, datum, i) + log.Println("bad bin format", this.Min, step, datum, i) } else { hist[i]++ }