GitHub PullRequestReviewCommentEvent at 2014-10-14 12:23:15
Repository: charmstore
Actor: mhilton
Payload: {"action":"created","comment":{"url":"https://api.github.com/repos/juju/charmstore/pulls/comments/18824356","id":18824356,"diff_hunk":"@@ -0,0 +1,284 @@\n+// Copyright 2014 Canonical Ltd.\n+// Licensed under the LGPLv3, see LICENCE file for details.\n+\n+package charmstore\n+\n+import (\n+\t\"encoding/json\"\n+\t\"net/url\"\n+\n+\t\"github.com/juju/errgo\"\n+\n+\t\"github.com/juju/charmstore/internal/elasticsearch\"\n+\t\"github.com/juju/charmstore/internal/mongodoc\"\n+)\n+\n+// StoreElasticSearch provides strongly typed methods for accessing the\n+// elasticsearch database. These methods will not return errors if\n+// elasticsearch is not configured, allowing them to be safely called even if\n+// it is not enabled in this service.\n+type StoreElasticSearch struct {\n+\t*elasticsearch.Database\n+\tIndex string\n+}\n+\n+const typeName = \"entity\"\n+\n+// Put inserts the mongodoc.Entity into elasticsearch if elasticsearch\n+// is configured.\n+func (ses *StoreElasticSearch) put(entity *mongodoc.Entity) error {\n+\tif ses == nil || ses.Database == nil {\n+\t\treturn nil\n+\t}\n+\treturn ses.PutDocument(ses.Index, typeName, ses.getID(entity), entity)\n+}\n+\n+// getID returns the id to be used for indexing the entity into ElasticSearch.\n+func (ses *StoreElasticSearch) getID(entity *mongodoc.Entity) string {\n+\treturn url.QueryEscape(entity.URL.String())\n+}\n+\n+// Search searches for entities. The query is a json string which conforms\n+// to the elasticsearch querydsl.\n+// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html\n+// Returns a slice containing each Id of the matching documents returned by\n+// elasticsearch.\n+func (ses *StoreElasticSearch) search(query string) ([]string, error) {\n+\tif ses == nil || ses.Database == nil {\n+\t\treturn nil, nil\n+\t}\n+\tresults, err := ses.Database.Search(ses.Index, typeName, query)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\tids := make([]string, 0, len(results.Hits.Hits))\n+\tfor _, hit := range results.Hits.Hits {\n+\t\tids = append(ids, hit.ID)\n+\t}\n+\treturn ids, nil\n+\t// TODO: return more than just ids e.g. total, hits, score, information, serach time\n+}\n+\n+// ExportToElasticSearch reads all of the mongodoc Entities and writes\n+// them to elasticsearch\n+func (store *Store) ExportToElasticSearch() error {\n+\tvar result mongodoc.Entity\n+\titer := store.DB.Entities().Find(nil).Iter()\n+\tdefer iter.Close()\n+\tfor iter.Next(&result) {\n+\t\tif err := store.ES.put(&result); err != nil {\n+\t\t\treturn errgo.Notef(err, \"cannot index %s\", result.URL)\n+\t\t}\n+\t}\n+\tif err := iter.Close(); err != nil {\n+\t\treturn err\n+\t}\n+\treturn nil\n+}\n+\n+// SearchParams represents the search parameters used by the store.\n+type SearchParams struct {\n+\t// The text to use in the full text search query.\n+\tText string\n+\t// If autocomplete is specified, the search will return only charms and\n+\t// bundles with a name that has text as a prefix.\n+\tAutoComplete bool\n+\t// Limit the search to items with attributes that match the specified filter value.\n+\tFilters map[string][]string\n+\t// Limit the number of returned items to the specified count.\n+\tLimit int\n+}\n+\n+// Search the store for the given SearchParams.\n+// Returns a slice containing each Id of the matching documents returned by\n+// elasticsearch.\n+func (store *Store) Search(sp SearchParams) ([]string, error) {\n+\tquery := createSearchDSL(sp)\n+\treturn store.ES.search(query)\n+}\n+\n+// createSearchDSL builds an elasticsearch query from the query parameters.\n+// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html\n+func createSearchDSL(sp SearchParams) string {\n+\tqdsl := elasticsearch.QueryDSL{\n+\t\tSize: sp.Limit,\n+\t}\n+\tvar q elasticsearch.Query\n+\tif sp.Text == \"\" {\n+\t\tq = elasticsearch.MatchAllQuery{}\n+\t} else if sp.AutoComplete {\n+\t\tq = elasticsearch.MultiMatchQuery{\n+\t\t\tQuery: sp.Text,\n+\t\t\tFields: []string{\n+\t\t\t\telasticsearch.BoostField(\"CharmMeta.Name.ngrams\", 10),\n+\t\t\t\telasticsearch.BoostField(\"CharmMeta.Description\", 3),\n+\t\t\t},\n+\t\t}\n+\t} else {\n+\t\tq = elasticsearch.MultiMatchQuery{\n+\t\t\tQuery: sp.Text,\n+\t\t\tFields: []string{\n+\t\t\t\telasticsearch.BoostField(\"CharmMeta.Name\", 10),\n+\t\t\t\telasticsearch.BoostField(\"CharmMeta.Description\", 3),\n+\t\t\t},\n+\t\t}\n+\t}\n+\n+\tq = elasticsearch.FunctionScoreQuery{\n+\t\tQuery: q,\n+\t\tFunctions: []elasticsearch.Function{\n+\t\t\t{\n+\t\t\t\tFunction: \"linear\",\n+\t\t\t\tField:    \"UploadTime\",\n+\t\t\t\tScale:    \"365d\",\n+\t\t\t},\n+\t\t},\n+\t}\n+\n+\tqdsl.Query = elasticsearch.FilteredQuery{\n+\t\tQuery:  q,\n+\t\tFilter: createFilters(sp.Filters),\n+\t}\n+\n+\tbytes, err := json.Marshal(qdsl)\n+\tif err != nil {\n+\t\tpanic(err)\n+\t}\n+\treturn string(bytes)\n+}\n+\n+// createFilters generates elasticsearch filters, based on the filter\n+// parameters\n+func createFilters(f map[string][]string) elasticsearch.Filter {\n+\taf := elasticsearch.AndFilter{}","path":"internal/charmstore/search.go","position":null,"original_position":153,"commit_id":"9028c9fa3a91a7ea019e52d2079ae3b55f1a1d2c","original_commit_id":"1890a8cd05004b757818e2367d1f3b818482a320","user":{"login":"mhilton","id":1136018,"avatar_url":"https://avatars.githubusercontent.com/u/1136018?v=2","gravatar_id":"","url":"https://api.github.com/users/mhilton","html_url":"https://github.com/mhilton","followers_url":"https://api.github.com/users/mhilton/followers","following_url":"https://api.github.com/users/mhilton/following{/other_user}","gists_url":"https://api.github.com/users/mhilton/gists{/gist_id}","starred_url":"https://api.github.com/users/mhilton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mhilton/subscriptions","organizations_url":"https://api.github.com/users/mhilton/orgs","repos_url":"https://api.github.com/users/mhilton/repos","events_url":"https://api.github.com/users/mhilton/events{/privacy}","received_events_url":"https://api.github.com/users/mhilton/received_events","type":"User","site_admin":false},"body":"done","created_at":"2014-10-14T12:23:15Z","updated_at":"2014-10-14T12:23:15Z","html_url":"https://github.com/juju/charmstore/pull/142#discussion_r18824356","pull_request_url":"https://api.github.com/repos/juju/charmstore/pulls/142","_links":{"self":{"href":"https://api.github.com/repos/juju/charmstore/pulls/comments/18824356"},"html":{"href":"https://github.com/juju/charmstore/pull/142#discussion_r18824356"},"pull_request":{"href":"https://api.github.com/repos/juju/charmstore/pulls/142"}}},"pull_request":{"url":"https://api.github.com/repos/juju/charmstore/pulls/142","id":22698863,"html_url":"https://github.com/juju/charmstore/pull/142","diff_url":"https://github.com/juju/charmstore/pull/142.diff","patch_url":"https://github.com/juju/charmstore/pull/142.patch","issue_url":"https://api.github.com/repos/juju/charmstore/issues/142","number":142,"state":"open","locked":false,"title":"Added search filter functions.","user":{"login":"mhilton","id":1136018,"avatar_url":"https://avatars.githubusercontent.com/u/1136018?v=2","gravatar_id":"","url":"https://api.github.com/users/mhilton","html_url":"https://github.com/mhilton","followers_url":"https://api.github.com/users/mhilton/followers","following_url":"https://api.github.com/users/mhilton/following{/other_user}","gists_url":"https://api.github.com/users/mhilton/gists{/gist_id}","starred_url":"https://api.github.com/users/mhilton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mhilton/subscriptions","organizations_url":"https://api.github.com/users/mhilton/orgs","repos_url":"https://api.github.com/users/mhilton/repos","events_url":"https://api.github.com/users/mhilton/events{/privacy}","received_events_url":"https://api.github.com/users/mhilton/received_events","type":"User","site_admin":false},"body":"Added support in the elasticsearch DSL for the\r\nfilter functions defined in http://tinyurl.com/qzobc69","created_at":"2014-10-14T09:40:00Z","updated_at":"2014-10-14T12:23:15Z","closed_at":null,"merged_at":null,"merge_commit_sha":"3e25919663ce7f3dca94adea7e202aa1adef4f10","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/juju/charmstore/pulls/142/commits","review_comments_url":"https://api.github.com/repos/juju/charmstore/pulls/142/comments","review_comment_url":"https://api.github.com/repos/juju/charmstore/pulls/comments/{number}","comments_url":"https://api.github.com/repos/juju/charmstore/issues/142/comments","statuses_url":"https://api.github.com/repos/juju/charmstore/statuses/9028c9fa3a91a7ea019e52d2079ae3b55f1a1d2c","head":{"label":"mhilton:search-filters","ref":"search-filters","sha":"9028c9fa3a91a7ea019e52d2079ae3b55f1a1d2c","user":{"login":"mhilton","id":1136018,"avatar_url":"https://avatars.githubusercontent.com/u/1136018?v=2","gravatar_id":"","url":"https://api.github.com/users/mhilton","html_url":"https://github.com/mhilton","followers_url":"https://api.github.com/users/mhilton/followers","following_url":"https://api.github.com/users/mhilton/following{/other_user}","gists_url":"https://api.github.com/users/mhilton/gists{/gist_id}","starred_url":"https://api.github.com/users/mhilton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mhilton/subscriptions","organizations_url":"https://api.github.com/users/mhilton/orgs","repos_url":"https://api.github.com/users/mhilton/repos","events_url":"https://api.github.com/users/mhilton/events{/privacy}","received_events_url":"https://api.github.com/users/mhilton/received_events","type":"User","site_admin":false},"repo":{"id":24229515,"name":"charmstore","full_name":"mhilton/charmstore","owner":{"login":"mhilton","id":1136018,"avatar_url":"https://avatars.githubusercontent.com/u/1136018?v=2","gravatar_id":"","url":"https://api.github.com/users/mhilton","html_url":"https://github.com/mhilton","followers_url":"https://api.github.com/users/mhilton/followers","following_url":"https://api.github.com/users/mhilton/following{/other_user}","gists_url":"https://api.github.com/users/mhilton/gists{/gist_id}","starred_url":"https://api.github.com/users/mhilton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mhilton/subscriptions","organizations_url":"https://api.github.com/users/mhilton/orgs","repos_url":"https://api.github.com/users/mhilton/repos","events_url":"https://api.github.com/users/mhilton/events{/privacy}","received_events_url":"https://api.github.com/users/mhilton/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mhilton/charmstore","description":"The charm store server.","fork":true,"url":"https://api.github.com/repos/mhilton/charmstore","forks_url":"https://api.github.com/repos/mhilton/charmstore/forks","keys_url":"https://api.github.com/repos/mhilton/charmstore/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mhilton/charmstore/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mhilton/charmstore/teams","hooks_url":"https://api.github.com/repos/mhilton/charmstore/hooks","issue_events_url":"https://api.github.com/repos/mhilton/charmstore/issues/events{/number}","events_url":"https://api.github.com/repos/mhilton/charmstore/events","assignees_url":"https://api.github.com/repos/mhilton/charmstore/assignees{/user}","branches_url":"https://api.github.com/repos/mhilton/charmstore/branches{/branch}","tags_url":"https://api.github.com/repos/mhilton/charmstore/tags","blobs_url":"https://api.github.com/repos/mhilton/charmstore/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mhilton/charmstore/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mhilton/charmstore/git/refs{/sha}","trees_url":"https://api.github.com/repos/mhilton/charmstore/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mhilton/charmstore/statuses/{sha}","languages_url":"https://api.github.com/repos/mhilton/charmstore/languages","stargazers_url":"https://api.github.com/repos/mhilton/charmstore/stargazers","contributors_url":"https://api.github.com/repos/mhilton/charmstore/contributors","subscribers_url":"https://api.github.com/repos/mhilton/charmstore/subscribers","subscription_url":"https://api.github.com/repos/mhilton/charmstore/subscription","commits_url":"https://api.github.com/repos/mhilton/charmstore/commits{/sha}","git_commits_url":"https://api.github.com/repos/mhilton/charmstore/git/commits{/sha}","comments_url":"https://api.github.com/repos/mhilton/charmstore/comments{/number}","issue_comment_url":"https://api.github.com/repos/mhilton/charmstore/issues/comments/{number}","contents_url":"https://api.github.com/repos/mhilton/charmstore/contents/{+path}","compare_url":"https://api.github.com/repos/mhilton/charmstore/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mhilton/charmstore/merges","archive_url":"https://api.github.com/repos/mhilton/charmstore/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mhilton/charmstore/downloads","issues_url":"https://api.github.com/repos/mhilton/charmstore/issues{/number}","pulls_url":"https://api.github.com/repos/mhilton/charmstore/pulls{/number}","milestones_url":"https://api.github.com/repos/mhilton/charmstore/milestones{/number}","notifications_url":"https://api.github.com/repos/mhilton/charmstore/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mhilton/charmstore/labels{/name}","releases_url":"https://api.github.com/repos/mhilton/charmstore/releases{/id}","created_at":"2014-09-19T12:48:28Z","updated_at":"2014-09-30T13:48:31Z","pushed_at":"2014-10-14T12:22:57Z","git_url":"git://github.com/mhilton/charmstore.git","ssh_url":"git@github.com:mhilton/charmstore.git","clone_url":"https://github.com/mhilton/charmstore.git","svn_url":"https://github.com/mhilton/charmstore","homepage":null,"size":1069,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"v4"}},"base":{"label":"juju:v4","ref":"v4","sha":"ea93d8bf018b12fcc187dd45a5a8a6a852839d7d","user":{"login":"juju","id":4604548,"avatar_url":"https://avatars.githubusercontent.com/u/4604548?v=2","gravatar_id":"","url":"https://api.github.com/users/juju","html_url":"https://github.com/juju","followers_url":"https://api.github.com/users/juju/followers","following_url":"https://api.github.com/users/juju/following{/other_user}","gists_url":"https://api.github.com/users/juju/gists{/gist_id}","starred_url":"https://api.github.com/users/juju/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/juju/subscriptions","organizations_url":"https://api.github.com/users/juju/orgs","repos_url":"https://api.github.com/users/juju/repos","events_url":"https://api.github.com/users/juju/events{/privacy}","received_events_url":"https://api.github.com/users/juju/received_events","type":"Organization","site_admin":false},"repo":{"id":20720417,"name":"charmstore","full_name":"juju/charmstore","owner":{"login":"juju","id":4604548,"avatar_url":"https://avatars.githubusercontent.com/u/4604548?v=2","gravatar_id":"","url":"https://api.github.com/users/juju","html_url":"https://github.com/juju","followers_url":"https://api.github.com/users/juju/followers","following_url":"https://api.github.com/users/juju/following{/other_user}","gists_url":"https://api.github.com/users/juju/gists{/gist_id}","starred_url":"https://api.github.com/users/juju/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/juju/subscriptions","organizations_url":"https://api.github.com/users/juju/orgs","repos_url":"https://api.github.com/users/juju/repos","events_url":"https://api.github.com/users/juju/events{/privacy}","received_events_url":"https://api.github.com/users/juju/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/juju/charmstore","description":"The charm store server.","fork":false,"url":"https://api.github.com/repos/juju/charmstore","forks_url":"https://api.github.com/repos/juju/charmstore/forks","keys_url":"https://api.github.com/repos/juju/charmstore/keys{/key_id}","collaborators_url":"https://api.github.com/repos/juju/charmstore/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/juju/charmstore/teams","hooks_url":"https://api.github.com/repos/juju/charmstore/hooks","issue_events_url":"https://api.github.com/repos/juju/charmstore/issues/events{/number}","events_url":"https://api.github.com/repos/juju/charmstore/events","assignees_url":"https://api.github.com/repos/juju/charmstore/assignees{/user}","branches_url":"https://api.github.com/repos/juju/charmstore/branches{/branch}","tags_url":"https://api.github.com/repos/juju/charmstore/tags","blobs_url":"https://api.github.com/repos/juju/charmstore/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/juju/charmstore/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/juju/charmstore/git/refs{/sha}","trees_url":"https://api.github.com/repos/juju/charmstore/git/trees{/sha}","statuses_url":"https://api.github.com/repos/juju/charmstore/statuses/{sha}","languages_url":"https://api.github.com/repos/juju/charmstore/languages","stargazers_url":"https://api.github.com/repos/juju/charmstore/stargazers","contributors_url":"https://api.github.com/repos/juju/charmstore/contributors","subscribers_url":"https://api.github.com/repos/juju/charmstore/subscribers","subscription_url":"https://api.github.com/repos/juju/charmstore/subscription","commits_url":"https://api.github.com/repos/juju/charmstore/commits{/sha}","git_commits_url":"https://api.github.com/repos/juju/charmstore/git/commits{/sha}","comments_url":"https://api.github.com/repos/juju/charmstore/comments{/number}","issue_comment_url":"https://api.github.com/repos/juju/charmstore/issues/comments/{number}","contents_url":"https://api.github.com/repos/juju/charmstore/contents/{+path}","compare_url":"https://api.github.com/repos/juju/charmstore/compare/{base}...{head}","merges_url":"https://api.github.com/repos/juju/charmstore/merges","archive_url":"https://api.github.com/repos/juju/charmstore/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/juju/charmstore/downloads","issues_url":"https://api.github.com/repos/juju/charmstore/issues{/number}","pulls_url":"https://api.github.com/repos/juju/charmstore/pulls{/number}","milestones_url":"https://api.github.com/repos/juju/charmstore/milestones{/number}","notifications_url":"https://api.github.com/repos/juju/charmstore/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/juju/charmstore/labels{/name}","releases_url":"https://api.github.com/repos/juju/charmstore/releases{/id}","created_at":"2014-06-11T09:53:37Z","updated_at":"2014-09-02T14:35:19Z","pushed_at":"2014-10-13T15:17:52Z","git_url":"git://github.com/juju/charmstore.git","ssh_url":"git@github.com:juju/charmstore.git","clone_url":"https://github.com/juju/charmstore.git","svn_url":"https://github.com/juju/charmstore","homepage":null,"size":3174,"stargazers_count":3,"watchers_count":3,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":11,"mirror_url":null,"open_issues_count":7,"forks":11,"open_issues":7,"watchers":3,"default_branch":"v4"}},"_links":{"self":{"href":"https://api.github.com/repos/juju/charmstore/pulls/142"},"html":{"href":"https://github.com/juju/charmstore/pull/142"},"issue":{"href":"https://api.github.com/repos/juju/charmstore/issues/142"},"comments":{"href":"https://api.github.com/repos/juju/charmstore/issues/142/comments"},"review_comments":{"href":"https://api.github.com/repos/juju/charmstore/pulls/142/comments"},"review_comment":{"href":"https://api.github.com/repos/juju/charmstore/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/juju/charmstore/pulls/142/commits"},"statuses":{"href":"https://api.github.com/repos/juju/charmstore/statuses/9028c9fa3a91a7ea019e52d2079ae3b55f1a1d2c"}}}}