Grouping and ungrouping search results

Grouping and ungrouping refer to the process of organizing the results of a search request in a specific way. The platform allows for grouping based on the unique identifiers of the videos. For example, this is useful when building a user interface, because it allows your users to better understand and navigate the search results. On the other hand, ungrouping presents your search results in a flat list. This is useful if you want to view all of the search results in a simple manner. Note that this feature can only be used with simple queries.

To group or ungroup items in a response, use the group_by parameter, specifying one of the following values:

  • video: The platform will group the matching video clips in the response by video.
  • clip: The matching video clips in the response will not be grouped.

📘

Note

The group_by parameter is optional and its default value is clip. If omitted, the platform will use the default value. For clarity, the examples in this section always specify the group_by parameter.

For a description of each field in the request and response, see the API Reference> Make any-to-video search requests page.

Prerequisites

  • You're familiar with the concepts that are described on the Platform overview page.
  • You've already created an index, and the Marengo video understanding engine is enabled for this index.
  • You've already uploaded a video, and the platform has finished indexing it.

Examples

Grouping items in a response

The following example code groups the matching video clips in the response by video:

from twelvelabs import TwelveLabs

client = TwelveLabs(api_key="<YOUR_API_KEY>")

search_results = client.search.query(
  index_id="<YOUR_INDEX_ID>, 
  query_text="<YOUR_QUERY>, 
  options=["visual"],
  group_by="video"
)

# Utility function to print a specific page
def print_page(page):
    for video in page:
        print(f"Video id: {video.id}")
        for clip in video.clips:
            print(clip)
            print(
                f"\tscore={clip.score} start={clip.start} end={clip.end} confidence={clip.confidence} metadata={clip.metadata}"
            )

print_page(search_results.data)

while True:
    try:
        print_page(next(search_results))
    except StopIteration:
        break
import { TwelveLabs, GroupByVideoSearchData } from 'twelvelabs-js';

const client = new TwelveLabs({ apiKey: '<YOUR_API_KEY>'});

let searchResults = await client.search.query({
  indexId: '<YOUR_INDEX_ID>'
  queryText: '<YOUR_QUERY>',
  options: ['visual'],
  groupBy: 'video',
});
printPage(searchResults);
while (true) {
  const page = await searchResults.next();
  if (page === null) break;
  else printPage(page);
}
// Utility function to print a specific page
function printPage(searchData) {
  (searchData.data as GroupByVideoSearchData[]).forEach((video) => {
    console.log(`videoId=${video.id}`);
    video.clips?.forEach((clip) => {
      console.log(
        `     score=${clip.score} start=${clip.start} end=${clip.end} confidence=${clip.confidence}`,
      );
    });
  });
}

The output should look similar to the following one:

Video id: 65d60bcf48db9fa780cb415e
score=83.73 start=273.96875 end=289.0625 video_id='65d60bcf48db9fa780cb415e' metadata=[{'type': 'visual'}] confidence='high'
	score=83.73 start=273.96875 end=289.0625 confidence=high metadata=[{'type': 'visual'}]
score=83.55 start=397.921875 end=439.84375 video_id='65d60bcf48db9fa780cb415e' metadata=[{'type': 'visual'}] confidence='high'
	score=83.55 start=397.921875 end=439.84375 confidence=high metadata=[{'type': 'visual'}]
score=83.46 start=294.5625 end=311.84375 video_id='65d60bcf48db9fa780cb415e' metadata=[{'type': 'visual'}] confidence='high'
Video id: 65d5fbad48db9fa780cb415c
score=83.36 start=342.6875 end=353.140625 video_id='65d5fbad48db9fa780cb415c' metadata=[{'type': 'visual'}] confidence='high' thumbnail_url=None module_confidence=None
	score=83.36 start=342.6875 end=353.140625 confidence=high metadata=[{'type': 'visual'}]
score=83.32 start=164.671875 end=200.71875 video_id='65d5fbad48db9fa780cb415c' metadata=[{'type': 'visual'}] confidence='high' thumbnail_url=None module_confidence=None
	score=83.32 start=164.671875 end=200.71875 confidence=high metadata=[{'type': 'visual'}]
score=83.31 start=329.96875 end=337.75 video_id='65d5fbad48db9fa780cb415c' metadata=[{'type': 'visual'}] confidence='high' thumbnail_url=None module_confidence=None
	score=83.31 start=329.96875 end=337.75 confidence=high metadata=[{'type': 'visual'}]

In this example, note that the data array contains a list of objects. Each object corresponds to a video that matches your query and is composed of the following key-value pairs:

  • clips: An array that groups the information about all the matching video clips in that video.
  • id: The unique identifier of the video that matched your query.

Ungrouping items in a response

The following example performs a search request, and the matching video clips in the response are not grouped:

from twelvelabs import TwelveLabs

client = TwelveLabs(api_key="<YOUR_API_KEY>")

search_results = client.search.query(
  index_id="<YOUR_INDEX_ID>",
  query_text=  "<YOUR_QUERY>"
  options=["visual"],
  group_by='clip'
)
# Utility function to print a specific page
def print_page(page):
  for clip in page:
    print(
        f" video_id={clip.video_id} score={clip.score} start={clip.start} end={clip.end} confidence={clip.confidence} metadata={clip.metadata}"
    )

print_page(search_results.data)

while True:
    try:
        print_page(next(search_results))
    except StopIteration:
        break
import { TwelveLabs, SearchData } from 'twelvelabs-js';

const client = new TwelveLabs({ apiKey: '<YOUR_API_KEY>'});

let searchResults = await client.search.query({
  indexId: '<YOUR_INDEX_ID>'
  queryText: '<YOUR_QUERY>',
  options: ['visual'],
  group_by='clip',
});
printPage(searchResults.data);
while (true) {
  const page = await searchResults.next();
  if (page === null) break;
  else printPage(page);
}
// Utility function to print a specific page
function printPage(searchData) {
  (searchData as SearchData[]).forEach((clip) => {
    console.log(
      `video_id= ${clip.videoId} score=${clip.score} start=${clip.start} end=${clip.end} confidence=${clip.confidence} metadata=${JSON.stringify(clip.metadata)}`,
    );
  });
}

The output should look similar to the following one:

video_id=65d6131c48db9fa780cb415f score=52.04 start=4.5625 end=14.8125 confidence=low metadata=[{'type': 'visual'}]
 video_id=65d6131c48db9fa780cb415f score=50.94 start=20.9375 end=25.09375 confidence=low metadata=[{'type': 'visual'}]
 video_id=65d60bcf48db9fa780cb415e score=50.94 start=20.9375 end=25.09375 confidence=low metadata=[{'type': 'visual'}]