示例#1
0
    def search(cls, **kwargs):
        kwargs.update({
            'using': connections.get_connection(),
            'index': cls.get_index(),
            'doc_type': {
                cls._doc_type.name: cls.from_es
            },
        })
        sq = Search(**kwargs)

        # Add highlighting.
        sq = sq.highlight(*cls.excerpt_fields)
        sq = sq.highlight_options(order='score')

        return sq
    def put(self) -> dict:
        """
        search for a group in Elasticsearch

        Returns:
            dict -- search results
        """
        args = self.parser.parse_args()

        # init search
        search: Search = Group.search()

        search_query: dict = {
            "bool": {
                "should": [
                    {"query_string": {"query": args["query"], "fields": ["*"]}},
                    {
                        "nested": {
                            "path": "topics",
                            "score_mode": "avg",
                            "query": {
                                "bool": {
                                    "must": [
                                        {
                                            "query_string": {
                                                "query": args["query"],
                                                "fields": ["*"],
                                            }
                                        }
                                    ]
                                }
                            },
                        }
                    },
                    {
                        "nested": {
                            "path": "events",
                            "score_mode": "avg",
                            "query": {
                                "bool": {
                                    "must": [
                                        {
                                            "query_string": {
                                                "query": args["query"],
                                                "fields": ["*"],
                                            }
                                        }
                                    ]
                                }
                            },
                        }
                    },
                ],
                "must": [],
            }
        }

        # set event time filter
        if args["event_time_gte"] or args["event_time_lte"]:
            range_query: dict = {}
            if args["event_time_gte"]:
                range_query["gte"] = args["event_time_gte"]
            if args["event_time_lte"]:
                range_query["lte"] = args["event_time_lte"]

            search_query["bool"]["must"].append(
                {
                    "nested": {
                        "path": "events",
                        "score_mode": "avg",
                        "query": {
                            "bool": {"must": [{"range": {"events.time": range_query}}]}
                        },
                    }
                }
            )

        # set geo_distance filter
        if args["geo_distance"] and args["geo_lat"] and args["geo_lon"]:
            search_query["bool"]["must"].append(
                {
                    "nested": {
                        "path": "events",
                        "score_mode": "avg",
                        "query": {
                            "bool": {
                                "must": [
                                    {
                                        "geo_distance": {
                                            "distance": args["geo_distance"],
                                            "events.venue_location": {
                                                "lat": args["geo_lat"],
                                                "lon": args["geo_lon"],
                                            },
                                        }
                                    }
                                ]
                            }
                        },
                    }
                }
            )

        # pagination
        strat_entry: int = args["page"] * args["limit"]
        end_entry: int = strat_entry + args["limit"]
        search = search[strat_entry:end_entry]

        # sort
        if args["sort"]:
            search = Search().sort(args["sort"])

        # execute search
        search = search.query(Q(search_query))

        # set highlight score
        search.highlight_options(order="score")

        # load response from elasticsearch
        results: Response = search.execute()

        # get response
        found_groups: List[dict] = []
        map_center_lat: float = 0
        map_center_lon: float = 0
        for group in results.hits:

            group_dict: dict = {}
            if isinstance(group, Hit):
                group_object = Group.get_group(urlname=group.to_dict()["urlname"])
                group_dict = group_object.to_json_dict(load_events=args["load_events"])
            else:
                group_dict = group.to_json_dict(load_events=args["load_events"])

            if "venue_location_average" in group_dict:
                map_center_lat = (
                    map_center_lat + group_dict["venue_location_average"]["lat"]
                )
                map_center_lon = (
                    map_center_lon + group_dict["venue_location_average"]["lon"]
                )
            else:
                map_center_lat = map_center_lat + group_dict["location"]["lat"]
                map_center_lon = map_center_lon + group_dict["location"]["lon"]

            # add group dict to array
            found_groups.append(
                {**group_dict,}
            )

        if len(found_groups) > 0:
            map_center_lat = map_center_lat / len(found_groups)
            map_center_lon = map_center_lon / len(found_groups)

        return {
            "results": found_groups,
            "hits": results.hits.total["value"],
            "map_center": {"lat": map_center_lat, "lon": map_center_lon},
        }