Fix search to return better results by searching for robots and namespaces in different queries.

This commit is contained in:
Joseph Schorr 2015-04-09 12:57:20 -04:00
parent 3707feaf5d
commit 396cba64e6
3 changed files with 46 additions and 29 deletions

View file

@ -679,14 +679,19 @@ def get_user_or_org_by_customer_id(customer_id):
except User.DoesNotExist:
return None
def get_matching_entities(entity_prefix):
matching_user_orgs = ((User.username ** (entity_prefix + '%')) & (User.robot == False))
matching_robots = ((User.username ** ('%+%' + entity_prefix + '%')) & (User.robot == True))
def get_matching_user_namespaces(namespace_prefix, username, limit=10):
query = (Repository
.select()
.join(Namespace, on=(Repository.namespace_user == Namespace.id))
.switch(Repository)
.join(Visibility)
.switch(Repository)
.join(RepositoryPermission, JOIN_LEFT_OUTER)
.where(Namespace.username ** (namespace_prefix + '%'))
.group_by(Repository.namespace_user, Repository)
.limit(limit))
query = (User.select()
.where(matching_user_orgs | matching_robots))
return query
return [r.namespace_user for r in _filter_to_repos_for_user(query, username)]
def get_matching_user_teams(team_prefix, user, limit=10):
query = (Team.select()
@ -699,6 +704,23 @@ def get_matching_user_teams(team_prefix, user, limit=10):
return query
def get_matching_robots(name_prefix, username, limit=10):
admined_orgs = (get_user_organizations(username)
.switch(Team)
.join(TeamRole)
.where(TeamRole.name == 'admin'))
prefix_checks = False
for org in admined_orgs:
prefix_checks = prefix_checks | (User.username ** (org.username + '+' + name_prefix + '%'))
prefix_checks = prefix_checks | (User.username ** (username + '+' + name_prefix + '%'))
return User.select().where(prefix_checks).limit(limit)
def get_matching_admined_teams(team_prefix, user, limit=10):
admined_orgs = (get_user_organizations(user.username)
.switch(Team)

View file

@ -227,22 +227,18 @@ def conduct_repo_search(username, query, results):
})
def conduct_entity_search(username, query, results):
""" Finds matching users, robots and organizations. """
matching_entities = model.get_matching_entities(query)
entity_count = 0
def conduct_namespace_search(username, query, results):
""" Finds matching users and organizations. """
matching_entities = model.get_matching_user_namespaces(query, username, limit=5)
for entity in matching_entities:
# If the entity is a robot, filter it to only match those that are under the current
# user or can be administered by the organization.
if entity.robot:
orgname = parse_robot_username(entity.username)[0]
if not AdministerOrganizationPermission(orgname).can() and not orgname == username:
continue
results.append(search_entity_view(username, entity))
entity_count = entity_count + 1
if entity_count >= 5:
break
def conduct_robot_search(username, query, results):
""" Finds matching robot accounts. """
matching_robots = model.get_matching_robots(query, username, limit=5)
for robot in matching_robots:
results.append(search_entity_view(username, robot))
@resource('/v1/find/all')
@ -269,11 +265,14 @@ class ConductSearch(ApiResource):
conduct_team_search(username, query, encountered_teams, results)
conduct_admined_team_search(username, query, encountered_teams, results)
# Search for robot accounts.
conduct_robot_search(username, query, results)
# Search for repos.
conduct_repo_search(username, query, results)
# Search for users, orgs and robots.
conduct_entity_search(username, query, results)
# Search for users and orgs.
conduct_namespace_search(username, query, results)
# Modify the results' scores via how close the query term is to each result's name.
for result in results:

View file

@ -479,9 +479,7 @@ class TestConductSearch(ApiTestCase):
json = self.getJsonResponse(ConductSearch,
params=dict(query='read'))
self.assertEquals(1, len(json['results']))
self.assertEquals(json['results'][0]['kind'], 'user')
self.assertEquals(json['results'][0]['name'], 'reader')
self.assertEquals(0, len(json['results']))
json = self.getJsonResponse(ConductSearch,
params=dict(query='owners'))
@ -493,9 +491,7 @@ class TestConductSearch(ApiTestCase):
json = self.getJsonResponse(ConductSearch,
params=dict(query='read'))
self.assertEquals(1, len(json['results']))
self.assertEquals(json['results'][0]['kind'], 'user')
self.assertEquals(json['results'][0]['name'], 'reader')
self.assertEquals(0, len(json['results']))
json = self.getJsonResponse(ConductSearch,
params=dict(query='public'))