def composite(query, sources, opts = {})
      results = invoke('Composite',
        query,
        opts,
        passthrough_opts: %i(
          web_file_type
          video_filters
          video_sort
          news_category
          news_location_override
          news_sort
        ),
        enum_opt_to_module: {
          web_file_type: FileType,
          video_filters: VideoFilter,
          video_sort: VideoSort,
          news_category: NewsCategory,
          news_sort: NewsSort
        },
        param_name_replacements: {
          video_sort: 'VideoSortBy',
          news_sort: 'NewsSortBy'
        },
        params: {
          sources: sources.collect { |source| enum_value(source, Source) },
          web_search_options: web_search_options_from_opts(opts, :web_),
          image_filters: image_filters_from_opts(opts, :image_)
        }
      )

      results.first
    end
def composite(query, sources, opts = {})
      results = invoke('Composite',
        query,
        opts,
        passthrough_opts: %i(
          web_file_type
          video_filters
          video_sort
          news_category
          news_location_override
          news_sort
        ),
        enum_opt_to_module: {
          web_file_type: FileType,
          video_filters: VideoFilter,
          video_sort: VideoSort,
          news_category: NewsCategory,
          news_sort: NewsSort
        },
        param_name_replacements: {
          video_sort: 'VideoSortBy',
          news_sort: 'NewsSortBy'
        },
        params: {
          sources: sources.collect { |source| enum_value(source, Source) },
          web_search_options: web_search_options_from_opts(opts, :web_),
          image_filters: image_filters_from_opts(opts, :image_)
        }
      )

      results.first
    end
Searches multiple sources. At most 15 news results are returned by
 a composite query regardless of the +:limit+ option.
 @macro general
 @param [Array<Source>] sources
   The sources to search
 @option opts [Boolean] :highlighting (false)
   Whether to surround query terms in {NewsResult#description} and
   {WebResult#description} with the delimiter {BingSearch::HIGHLIGHT_DELIMITER}.
 @option opts [FileType] :web_file_type
   Type of file to return. Applies to {Source::Web}; also affects
   {Source::Image} and {Source::Video} if {Source::Web} is specified.
 @option opts [Boolean] :web_host_collapsing (true)
   Whether to suppress results from the same 'top-level URL.' Applies to {Source::Web}.
 @option opts [Boolean] :web_query_alterations (true)
   Whether to alter the query in case of, e.g., supposed spelling errors. Applies to {Source::Web}.
 @option opts [Integer] :image_minimum_width
   In pixels; ANDed with other filters. Applies to {Source::Image}.
 @option opts [Integer] :image_minimum_height
   In pixels; ANDed with other image filters. Applies to {Source::Image}.
 @option opts [Array<ImageFilter>] :image_filters
   Multiple filters are ANDed. Applies to {Source::Image}.
 @option opts [Array<VideoFilter>] :video_filters
   Multiple filters are ANDed. At most one duration is allowed. Applies to {Source::Video}.
 @option opts [VideoSort] :video_sort
   Applies to {Source::Video}
 @option opts [NewsCategory] :news_category
   Only applies in the en_US market. If no news matches the category, Bing
   returns results from a mix of categories. Applies to {Source::News}.
 @option opts [String] :news_location_override
   Overrides Bing's location detection. Example: +US.WA+. Applies to {Source::News}.
 @option opts [NewsSort] :news_sort
   Applies to {Source::News}.

 @return [CompositeSearchResult]