def _search_users(session, search_query, title_only, next_rank, page_size, context, include_users): if not include_users: return [] rank, snippet, do_search_query = _gen_search_elements( search_query, title_only, next_rank, page_size, [User.username, User.name], [User.city], [User.about_me], [ User.my_travels, User.things_i_like, User.about_place, User.additional_information ], ) users = do_search_query( session.query(User, rank, snippet).filter(~User.is_banned)) return [ search_pb2.Result( rank=rank, # TODO: user_model_to_pb should accept just user_id, not full context user=user_model_to_pb(page, session, context), snippet=snippet, ) for page, rank, snippet in users ]
def _search_clusters(session, search_query, title_only, next_rank, page_size, user_id, include_communities, include_groups): if not include_communities and not include_groups: return [] rank, snippet, do_search_query = _gen_search_elements( search_query, title_only, next_rank, page_size, [Cluster.name], [PageVersion.address, PageVersion.title], [Cluster.description], [PageVersion.content], ) latest_pages = (session.query(func.max(PageVersion.id).label("id")).join( Page, Page.id == PageVersion.page_id).filter( Page.type == PageType.main_page).group_by( PageVersion.page_id).subquery()) clusters = do_search_query( session.query(Cluster, rank, snippet).join( Page, Page.owner_cluster_id == Cluster.id).join( PageVersion, PageVersion.page_id == Page.id).join( latest_pages, latest_pages.c.id == PageVersion.id). filter(Cluster.is_official_cluster if include_communities and not include_groups else True).filter( ~Cluster.is_official_cluster if not include_communities and include_groups else True)) return [ search_pb2.Result( rank=rank, community=community_to_pb(cluster.official_cluster_for_node, user_id) if cluster.is_official_cluster else None, group=group_to_pb(cluster, user_id) if not cluster.is_official_cluster else None, snippet=snippet, ) for cluster, rank, snippet in clusters ]
def _search_pages(session, search_query, title_only, next_rank, page_size, user_id, include_places, include_guides): rank, snippet, do_search_query = _gen_search_elements( search_query, title_only, next_rank, page_size, [PageVersion.title], [PageVersion.address], [], [PageVersion.content], ) if not include_places and not include_guides: return [] latest_pages = (session.query(func.max(PageVersion.id).label("id")).join( Page, Page.id == PageVersion.page_id).filter( or_( (Page.type == PageType.place) if include_places else False, (Page.type == PageType.guide) if include_guides else False, )).group_by(PageVersion.page_id).subquery()) pages = do_search_query( session.query(Page, rank, snippet).join(PageVersion, PageVersion.page_id == Page.id).join( latest_pages, latest_pages.c.id == PageVersion.id)) return [ search_pb2.Result( rank=rank, place=page_to_pb(page, user_id) if page.type == PageType.place else None, guide=page_to_pb(page, user_id) if page.type == PageType.guide else None, snippet=snippet, ) for page, rank, snippet in pages ]
def UserSearch(self, request, context): with session_scope() as session: query = session.query(User).filter(~User.is_banned) if request.HasField("query"): if request.query_name_only: query = query.filter( or_(User.name.ilike(f"%{request.query.value}%"), User.username.ilike(f"%{request.query.value}%"))) else: query = query.filter( or_( User.name.ilike(f"%{request.query.value}%"), User.username.ilike(f"%{request.query.value}%"), User.city.ilike(f"%{request.query.value}%"), User.hometown.ilike(f"%{request.query.value}%"), User.about_me.ilike(f"%{request.query.value}%"), User.my_travels.ilike(f"%{request.query.value}%"), User.things_i_like.ilike( f"%{request.query.value}%"), User.about_place.ilike(f"%{request.query.value}%"), User.additional_information.ilike( f"%{request.query.value}%"), )) if request.HasField("last_active"): raw_dt = to_aware_datetime(request.last_active) coarsened_dt = raw_dt.replace(minute=(raw_dt.minute // 15) * 15, second=0, microsecond=0) query = query.filter(User.last_active >= coarsened_dt) if request.HasField("gender"): query = query.filter( User.gender.ilike(f"%{request.gender.value}%")) if len(request.hosting_status_filter) > 0: query = query.filter( User.hosting_status.in_([ hostingstatus2sql[status] for status in request.hosting_status_filter ])) if len(request.smoking_location_filter) > 0: query = query.filter( User.smoking_allowed.in_([ smokinglocation2sql[loc] for loc in request.smoking_location_filter ])) if len(request.sleeping_arrangement_filter) > 0: query = query.filter( User.sleeping_arrangement.in_([ sleepingarrangement2sql[arr] for arr in request.sleeping_arrangement_filter ])) if len(request.parking_details_filter) > 0: query = query.filter( User.parking_details.in_([ parkingdetails2sql[det] for det in request.parking_details_filter ])) if request.HasField("guests"): query = query.filter(User.max_guests >= request.guests.value) if request.HasField("last_minute"): query = query.filter(User.last_minute == last_minute.value) if request.HasField("has_pets"): query = query.filter(User.has_pets == has_pets.value) if request.HasField("accepts_pets"): query = query.filter(User.accepts_pets == accepts_pets.value) if request.HasField("has_kids"): query = query.filter(User.has_kids == has_kids.value) if request.HasField("accepts_kids"): query = query.filter(User.accepts_kids == accepts_kids.value) if request.HasField("has_housemates"): query = query.filter( User.has_housemates == has_housemates.value) if request.HasField("wheelchair_accessible"): query = query.filter( User.wheelchair_accessible == wheelchair_accessible.value) if request.HasField("smokes_at_home"): query = query.filter( User.smokes_at_home == smokes_at_home.value) if request.HasField("drinking_allowed"): query = query.filter( User.drinking_allowed == drinking_allowed.value) if request.HasField("drinks_at_home"): query = query.filter( User.drinks_at_home == drinks_at_home.value) if request.HasField("parking"): query = query.filter(User.parking == parking.value) if request.HasField("camping_ok"): query = query.filter(User.camping_ok == camping_ok.value) if request.HasField("search_in_area"): # EPSG4326 measures distance in decimal degress # we want to check whether two circles overlap, so check if the distance between their centers is less # than the sum of their radii, divided by 111111 m ~= 1 degree (at the equator) search_point = create_coordinate(request.search_in_area.lat, request.search_in_area.lng) query = query.filter( func.ST_DWithin( User.geom, search_point, (User.geom_radius + request.search_in_area.radius) / 111111)) if request.HasField("search_in_community_id"): # could do a join here as well, but this is just simpler node = session.query(Node).filter( Node.id == request.search_in_community_id).one_or_none() if not node: context.abort(grpc.StatusCode.NOT_FOUND, errors.COMMUNITY_NOT_FOUND) query = query.filter(func.ST_Contains(node.geom, User.geom)) if request.only_with_references: query = query.join(Reference, Reference.to_user_id == User.id) # TODO: # google.protobuf.StringValue language = 11; # bool friends_only = 13; # google.protobuf.UInt32Value age_min = 14; # google.protobuf.UInt32Value age_max = 15; page_size = min(MAX_PAGINATION_LENGTH, request.page_size or MAX_PAGINATION_LENGTH) next_user_id = int(request.page_token) if request.page_token else 0 users = query.filter(User.id >= next_user_id).order_by( User.id).limit(page_size + 1).all() return search_pb2.UserSearchRes( results=[ search_pb2.Result( rank=1, user=user_model_to_pb(user, session, context), ) for user in users[:page_size] ], next_page_token=str(users[-1].id) if len(users) > page_size else None, )