From 1fe44e827a332a92f0211b37fa96be6730aa9d0b Mon Sep 17 00:00:00 2001 From: Alex Yatskov Date: Wed, 25 Mar 2015 12:33:41 +0900 Subject: [PATCH] Work in progress --- server.go | 82 +++++++++++++++++++++++++++++-------------------------- types.go | 20 ++++++-------- util.go | 35 ++++++++++++++++-------- 3 files changed, 75 insertions(+), 62 deletions(-) diff --git a/server.go b/server.go index f319ae6..7e8098a 100644 --- a/server.go +++ b/server.go @@ -48,53 +48,57 @@ func executeQuery(rw http.ResponseWriter, req *http.Request) { geo.longitude = request.Geo.Longitude } - context := queryContext{geo, convertFeatures(request.Profile), request.WalkingDist} + context := queryContext{geo, request.Profile, request.WalkingDist} entries := getRecords(context) - foundEntries := findRecords(entries, featureMap(request.Features), request.MinScore) + foundEntries := findRecords(entries, request.Features, request.MinScore) - // function runQuery(query, callback) { - // query.profile = fixupProfile(query.profile); - // query.features = fixupFeatures(query.features); + var response jsonQueryResponse + for featureName, featureValue := range request.Features { + column := jsonColumn{Value: featureValue, Steps: request.HintSteps} - // var context = { - // geo: query.geo, - // profile: query.profile, - // walkingDist: query.walkingDist * 1000.0 - // }; + hints := project( + foundEntries, + request.Features, + featureName, + request.MinScore, + queryBounds{min: request.Range.Min, max: request.Range.Max}, + request.HintSteps) - // getRecords(context, function(data) { - // var searchResults = findRecords( - // data, - // query.features, - // query.minScore - // ); + for _, hint := range hints { + jsonHint := jsonProjection{ + Sample: hint.sample, + Stats: jsonStats{Count: hint.stats.count, Compatibility: hint.stats.compatibility}} + column.Hints = append(column.Hints, jsonHint) + } - // var graphColumns = {}; - // for (var feature in query.features) { - // var searchHints = buildHints( - // data, - // query.features, - // feature, - // query.minScore, - // query.range, - // query.hintSteps - // ); + response.Columns[featureName] = column + } - // graphColumns[feature] = { - // value: query.features[feature], - // hints: searchHints, - // steps: query.hintSteps - // }; - // } + for entryIndex, entryValue := range foundEntries { + if entryIndex > request.MaxResults { + break + } - // callback({ - // columns: graphColumns, - // items: searchResults.slice(0, query.maxResults), - // count: searchResults.length - // }); - // }); - // } + jsonEntry := jsonRecord{ + Name: entryValue.name, + Score: entryValue.score, + DistanceToUser: entryValue.distanceToUser, + DistanceToStn: entryValue.distanceToStn, + ClosestStn: entryValue.closestStn, + AccessCount: entryValue.accessCount, + Id: entryValue.id} + + response.Items = append(response.Items, jsonEntry) + } + + js, err := json.Marshal(response) + if err != nil { + log.Fatal(err) + } + + rw.Header().Set("Content-Type", "application/json") + rw.Write(js) } func getCategories(rw http.ResponseWriter, req *http.Request) { diff --git a/types.go b/types.go index 4d9ed40..43e013d 100644 --- a/types.go +++ b/types.go @@ -22,7 +22,7 @@ package main -type jsonFeatureMap map[string]float64 +type featureMap map[string]float64 type jsonRange struct { Max float64 `json:"max"` @@ -36,14 +36,14 @@ type jsonGeo struct { } type jsonQueryRequest struct { - Features jsonFeatureMap `json:"features"` - Geo *jsonGeo `json:"geo"` - HintSteps int `json:"hintSteps"` - MaxResults int `json:"maxResults"` - MinScore float64 `json:"minScore"` - Profile jsonFeatureMap `json:"profile"` - Range jsonRange `json:"range"` - WalkingDist float64 `json:"walkingDist"` + Features featureMap `json:"features"` + Geo *jsonGeo `json:"geo"` + HintSteps int `json:"hintSteps"` + MaxResults int `json:"maxResults"` + MinScore float64 `json:"minScore"` + Profile featureMap `json:"profile"` + Range jsonRange `json:"range"` + WalkingDist float64 `json:"walkingDist"` } type jsonColumn struct { @@ -154,5 +154,3 @@ func (slice records) Less(i, j int) bool { func (slice records) Swap(i, j int) { slice[i], slice[j] = slice[j], slice[i] } - -type featureMap map[interface{}]float64 diff --git a/util.go b/util.go index b590992..1e2c39a 100644 --- a/util.go +++ b/util.go @@ -27,17 +27,9 @@ import ( "log" "math" "sort" + "strconv" ) -func convertFeatures(features jsonFeatureMap) featureMap { - resultMap := make(featureMap) - for key, value := range features { - resultMap[key] = value - } - - return resultMap -} - func innerProduct(features1 featureMap, features2 featureMap) float64 { var result float64 for key, value1 := range features1 { @@ -171,7 +163,7 @@ func computeRecordPopularity(entries records, context queryContext) { log.Fatal(err) } - recordProfile[categoryId] = categoryValue + recordProfile[strconv.Itoa(categoryId)] = categoryValue } if err := groupRows.Err(); err != nil { log.Fatal(err) @@ -205,9 +197,28 @@ func getRecords(context queryContext) records { var delicious, accomodating, affordable, atmospheric, latitude, longitude, distanceToStn float64 var accessCount, id int - rows.Scan(&name, &url, &delicious, &accomodating, &affordable, &atmospheric, &latitude, &longitude, &distanceToStn, &closestStn, &accessCount, &id) + rows.Scan( + &name, + &url, + &delicious, + &accomodating, + &affordable, + &atmospheric, + &latitude, + &longitude, + &distanceToStn, + &closestStn, + &accessCount, + &id) + + entry := record{ + name: name, + url: url, + distanceToStn: distanceToStn, + closestStn: closestStn, + accessCount: accessCount, + id: id} - entry := record{name: name, url: url, distanceToStn: distanceToStn, closestStn: closestStn, accessCount: accessCount, id: id} entry.features["delicious"] = delicious entry.features["accomodating"] = accomodating entry.features["affordable"] = affordable