1
This commit is contained in:
Alex Yatskov 2015-08-23 20:03:26 +09:00
parent fabde8de5f
commit c580e44f1a
3 changed files with 43 additions and 41 deletions

View File

@ -44,7 +44,7 @@ import (
var db *sql.DB var db *sql.DB
func prepareColumn(steps int, minScore float64, allEntries, matchedEntries []record, features featureMap, modes modeMap, name string, col *column, wg *sync.WaitGroup) { func prepareColumn(steps int, minScore float64, allEntries, matchedEntries []record, features map[string]float64, modes map[string]modeType, name string, col *column, wg *sync.WaitGroup) {
defer wg.Done() defer wg.Done()
*col = column{ *col = column{
@ -86,16 +86,16 @@ func executeQuery(rw http.ResponseWriter, req *http.Request) {
var ( var (
request struct { request struct {
Features featureMap `json:"features"` Features map[string]float64 `json:"features"`
Geo *geoData `json:"geo"` Geo *geoData `json:"geo"`
MaxResults int `json:"maxResults"` MaxResults int `json:"maxResults"`
MinScore float64 `json:"minScore"` MinScore float64 `json:"minScore"`
Modes map[string]string `json:"modes"` Modes map[string]string `json:"modes"`
Profile featureMap `json:"profile"` Profile map[string]float64 `json:"profile"`
Resolution int `json:"resolution"` Resolution int `json:"resolution"`
SortAsc bool `json:"sortAsc"` SortAsc bool `json:"sortAsc"`
SortKey string `json:"sortKey"` SortKey string `json:"sortKey"`
WalkingDist float64 `json:"walkingDist"` WalkingDist float64 `json:"walkingDist"`
} }
response struct { response struct {
@ -125,14 +125,10 @@ func executeQuery(rw http.ResponseWriter, req *http.Request) {
sorter := recordSorter{entries: matchedEntries, key: request.SortKey, ascending: request.SortAsc} sorter := recordSorter{entries: matchedEntries, key: request.SortKey, ascending: request.SortAsc}
sorter.sort() sorter.sort()
response.Columns = make(map[string]*column)
response.Count = len(matchedEntries)
response.MinScore = request.MinScore
response.Records = matchedEntries //[:request.MaxResults]
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(len(features)) wg.Add(len(features))
response.Columns = make(map[string]*column)
for name := range features { for name := range features {
response.Columns[name] = new(column) response.Columns[name] = new(column)
go prepareColumn( go prepareColumn(
@ -149,8 +145,16 @@ func executeQuery(rw http.ResponseWriter, req *http.Request) {
wg.Wait() wg.Wait()
response.Count = len(matchedEntries)
response.MinScore = request.MinScore
response.ElapsedTime = time.Since(startTime).Nanoseconds() response.ElapsedTime = time.Since(startTime).Nanoseconds()
if len(matchedEntries) > request.MaxResults {
response.Records = matchedEntries[:request.MaxResults]
} else {
response.Records = matchedEntries
}
js, err := json.Marshal(response) js, err := json.Marshal(response)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
@ -279,8 +283,8 @@ func removeCategory(rw http.ResponseWriter, req *http.Request) {
func accessReview(rw http.ResponseWriter, req *http.Request) { func accessReview(rw http.ResponseWriter, req *http.Request) {
var request struct { var request struct {
Id int `json:"id"` Id int `json:"id"`
Profile featureMap `json:"profile"` Profile map[string]float64 `json:"profile"`
} }
if err := json.NewDecoder(req.Body).Decode(&request); err != nil { if err := json.NewDecoder(req.Body).Decode(&request); err != nil {

View File

@ -27,15 +27,18 @@ import (
"sort" "sort"
) )
type featureMap map[string]float64
type modeMap map[string]modeType
type modeType int type modeType int
const ( const (
modeTypeProd = iota + 1 modeTypeProd modeType = iota + 1
modeTypeDist modeTypeDist
) )
type bracket struct {
Min float64 `json:"min"`
Max float64 `json:"max"`
}
type column struct { type column struct {
Bracket bracket `json:"bracket"` Bracket bracket `json:"bracket"`
Hints []projection `json:"hints"` Hints []projection `json:"hints"`
@ -60,18 +63,13 @@ type record struct {
Name string `json:"name"` Name string `json:"name"`
Score float64 `json:"score"` Score float64 `json:"score"`
Url string `json:"url"` Url string `json:"url"`
features featureMap features map[string]float64
geo geoData geo geoData
} }
type bracket struct {
Min float64 `json:"min"`
Max float64 `json:"max"`
}
type queryContext struct { type queryContext struct {
geo *geoData geo *geoData
profile featureMap profile map[string]float64
walkingDist float64 walkingDist float64
} }

26
util.go
View File

@ -31,8 +31,8 @@ import (
"github.com/kellydunn/golang-geo" "github.com/kellydunn/golang-geo"
) )
func fixFeatures(features featureMap) featureMap { func fixFeatures(features map[string]float64) map[string]float64 {
fixedFeatures := featureMap{ fixedFeatures := map[string]float64{
"nearby": 0.0, "nearby": 0.0,
"accessible": 0.0, "accessible": 0.0,
"delicious": 0.0, "delicious": 0.0,
@ -49,8 +49,8 @@ func fixFeatures(features featureMap) featureMap {
return fixedFeatures return fixedFeatures
} }
func fixModes(modes map[string]string) modeMap { func fixModes(modes map[string]string) map[string]modeType {
fixedModes := modeMap{ fixedModes := map[string]modeType{
"nearby": modeTypeProd, "nearby": modeTypeProd,
"accessible": modeTypeProd, "accessible": modeTypeProd,
"delicious": modeTypeProd, "delicious": modeTypeProd,
@ -69,7 +69,7 @@ func fixModes(modes map[string]string) modeMap {
return fixedModes return fixedModes
} }
func similarity(features1 featureMap, features2 featureMap) float64 { func similarity(features1 map[string]float64, features2 map[string]float64) float64 {
var result float64 var result float64
for key, value1 := range features1 { for key, value1 := range features1 {
@ -81,7 +81,7 @@ func similarity(features1 featureMap, features2 featureMap) float64 {
return result return result
} }
func compare(features1 featureMap, features2 featureMap, modes modeMap) float64 { func compare(features1 map[string]float64, features2 map[string]float64, modes map[string]modeType) float64 {
var result float64 var result float64
for key, value1 := range features1 { for key, value1 := range features1 {
@ -100,7 +100,7 @@ func compare(features1 featureMap, features2 featureMap, modes modeMap) float64
return result return result
} }
func walkMatches(entries []record, features featureMap, modes modeMap, minScore float64, callback func(record, float64)) { func walkMatches(entries []record, features map[string]float64, modes map[string]modeType, minScore float64, callback func(record, float64)) {
for _, entry := range entries { for _, entry := range entries {
if score := compare(features, entry.features, modes); score >= minScore { if score := compare(features, entry.features, modes); score >= minScore {
callback(entry, score) callback(entry, score)
@ -108,7 +108,7 @@ func walkMatches(entries []record, features featureMap, modes modeMap, minScore
} }
} }
func statRecords(entries []record, features featureMap, modes modeMap, minScore float64) (float64, int) { func statRecords(entries []record, features map[string]float64, modes map[string]modeType, minScore float64) (float64, int) {
var compatibility float64 var compatibility float64
var count int var count int
@ -132,7 +132,7 @@ func stepRange(min, max float64, steps int, callback func(float64)) {
} }
} }
func findRecords(entries []record, features featureMap, modes modeMap, minScore float64) []record { func findRecords(entries []record, features map[string]float64, modes map[string]modeType, minScore float64) []record {
var matchedEntries []record var matchedEntries []record
walkMatches(entries, features, modes, minScore, func(entry record, score float64) { walkMatches(entries, features, modes, minScore, func(entry record, score float64) {
@ -143,8 +143,8 @@ func findRecords(entries []record, features featureMap, modes modeMap, minScore
return matchedEntries return matchedEntries
} }
func project(entries []record, features featureMap, modes modeMap, featureName string, minScore float64, steps int) []projection { func project(entries []record, features map[string]float64, modes map[string]modeType, featureName string, minScore float64, steps int) []projection {
sampleFeatures := make(featureMap) sampleFeatures := make(map[string]float64)
for key, value := range features { for key, value := range features {
sampleFeatures[key] = value sampleFeatures[key] = value
} }
@ -219,7 +219,7 @@ func computeRecordCompat(entry *record, context queryContext, wg *sync.WaitGroup
} }
defer groupRows.Close() defer groupRows.Close()
recordProfile := make(featureMap) recordProfile := make(map[string]float64)
for groupRows.Next() { for groupRows.Next() {
var categoryId int var categoryId int
var categoryValue float64 var categoryValue float64
@ -305,7 +305,7 @@ func getRecords(context queryContext) []record {
geo: geoData{latitude, longitude}, geo: geoData{latitude, longitude},
Id: id} Id: id}
entry.features = featureMap{ entry.features = map[string]float64{
"delicious": delicious, "delicious": delicious,
"accommodating": accommodating, "accommodating": accommodating,
"affordable": affordable, "affordable": affordable,