# GPU Shortage? Make the most out of your GPUs with Compute Orchestration.

## Group or separate items in your search

You can add together multiple search parameters to expand your search. You can even combine negated search terms for more advanced tasks.

In annotation search, `Filter` and `Rank` is a list of `Annotation` objects. Filtered annotations will be ANDed.

### OR Search Operation

The **OR** filter lets you expand your search to include results that match any of the specified conditions, rather than requiring all of them to be met.

- Python SDK
- Node.js SDK

```python
# Import necessary modules
from clarifai.client.search import Search
from clarifai.client.user import User
from google.protobuf import struct_pb2
from PIL import Image
import requests
from IPython.display import display

# User-specific credentials
USER_ID = ''  # User ID
APP_ID = ''   # Application ID
PAT = ''      # Personal Access Token

# Define dataset and image URL
CREATE_DATASET_ID = "ci_search_dataset"
DOG_IMG_URL = "https://samples.clarifai.com/dog.tiff"

# Create Clarifai application
app_obj = User(user_id=USER_ID, pat=PAT).create_app(app_id=APP_ID, base_workflow="General")

# Create a dataset
dataset_obj = app_obj.create_dataset(CREATE_DATASET_ID)

# Initialize inputs object
inp_obj = app_obj.inputs()

# Define metadata for the image
metadata = struct_pb2.Struct()
metadata.update({"Breed": "Saint Bernard"})

# Get input from URL and upload it
input_proto = inp_obj.get_input_from_url(
        dataset_id=CREATE_DATASET_ID,
        input_id="dog-tiff",
        image_url=DOG_IMG_URL,
        labels=["dog"],
        geo_info=[-30.0, 40.0],  # longitude, latitude
        metadata=metadata)
inp_obj.upload_inputs([input_proto])

# Define OR filter
or_filter = [{  # OR
              "concepts": [{
                  "name": "deer",
                  "value": 1
              }, {
                  "name": "dog",
                  "value": 1
              }]}
          ]

# Perform search with OR filter
search = app_obj.search()
res = search.query(ranks=[{"image_url": "https://samples.clarifai.com/dog.tiff"}], filters=or_filter)

# Process search results
resp = list(res)
for r in resp:
    hit = r.hits[0].input.data.image.url
    break

# Display the image
print(hit)
hit_img = Image.open(requests.get(hit, stream=True).raw).resize((300,250))
display(hit_img)
```

### AND Search Operation

The **AND** operation enables you to refine search results by specifying multiple conditions that must all be satisfied at the same time.

For example, if a user searches for images containing both the concepts "dog" and "deer," only those images labeled with both concepts will be returned.

- Python SDK
- Node.js SDK

# Define user-specific credentials
USER_ID=''
APP_ID=''
PAT=''

# Define constants
CREATE_DATASET_ID = "ci_search_dataset"
DOG_IMG_URL = "https://samples.clarifai.com/dog.tiff"

# Create a new application
app_obj = User(user_id=USER_ID, pat=PAT).create_app(app_id=APP_ID, base_workflow="General")

# Create a new dataset
dataset_obj = app_obj.create_dataset(CREATE_DATASET_ID)

# Initialize Inputs object for uploading data
inp_obj = app_obj.inputs()

# Define metadata for the input
metadata = struct_pb2.Struct()
metadata.update({"Breed": "Saint Bernard"})

# Get input from URL and upload it to the dataset
input_proto = inp_obj.get_input_from_url(
        dataset_id=CREATE_DATASET_ID,
        input_id="dog-tiff",
        image_url=DOG_IMG_URL,
        labels=["dog"],
        geo_info=[-30.0, 40.0],  # longitude, latitude
        metadata=metadata)
inp_obj.upload_inputs([input_proto])

# Define an AND filter
and_filter = [{  # AND
                  "concepts": [{
                      "name": "dog",
                      "value": 1
                  }]} ,
              {  
                  "concepts": [{
                      "name": "deer",
                      "value": 1
                  }]}
              ]

# Create a search object
search = app_obj.search()

# Perform a search query with the specified rank and AND filter
res = search.query(ranks=[{"image_url": "https://samples.clarifai.com/dog.tiff"}], filters=and_filter)

# Convert search results to a list
resp = list(res)

# Print the length of the search results
print(len(resp)) # Should be zero
```

### Combine Filter and Rank

When you combine both `Filter` and `Rank`, filter will be applied before ranking annotations. This is important because limiting the results set on large applications can speed up the overall query drastically when doing a ranking.

- Python SDK
- Node.js SDK
- Python (gRPC)
- JavaScript (REST)
- Node.js (gRPC)
- Java (gRPC)
- PHP (gRPC)
- cURL

```python
from clarifai.client.search import Search
from clarifai.client.input import Inputs
from PIL import Image
import requests
from IPython.display import display

# Define your Clarifai credentials
USER_ID = ''
APP_ID = ''
PAT = ''

# Initialize the Clarifai client with your credentials
client = User(user_id=USER_ID)

# Create an application within Clarifai with the specified ID and base workflow
# The 'Universal' workflow is a general-purpose workflow that can handle various types of data
app = client.create_app(app_id=APP_ID, base_workflow="Universal", pat=PAT)

# Initialize a search object for the specified user, application, and access token
s = Search(user_id=USER_ID, app_id=APP_ID, pat=PAT)

# Initialize an Inputs object for the specified user, application, and access token
inp_obj = Inputs(user_id=USER_ID, app_id=APP_ID, pat=PAT)

# Prepare an input protobuf message from the provided image URL
input_proto = inp_obj.get_input_from_url(
        input_id="dog-tiff",
        image_url="https://samples.clarifai.com/dog.tiff",
        labels=["dog"],
        geo_info=[-30.0, 40.0],  # longitude, latitude
)

# Upload the prepared input protobuf message to the Clarifai application
inp_obj.upload_inputs([input_proto])

# Perform a search query with specified ranks and filters
response = s.query(ranks=[{"image_url": "https://samples.clarifai.com/dog.tiff"}], filters=[{"concepts": [{'name':'dog','value':1}]}])

# Process the response to extract the URL of the first matching image
resp = list(response)
for r in resp:
    hit = r.hits[0].input.data.image.url
    break

# Print the URL of the matched image
print(hit)

# Open the matched image URL, resize it, and display it
hit_img = Image.open(requests.get(hit, stream=True).raw).resize((300,250))
display(hit_img)
```

### Combine Filter by Metadata and Rank

You can also search over custom metadata and easily rank the results.

- Python (gRPC)
- JavaScript (REST)
- Node.js (gRPC)
- Java (gRPC)
- PHP (gRPC)
- cURL

```python
################################################################################
# In this section, we set the user authentication, app ID, and the concept we
# we want to search by. Change these strings to run your own example.
################################################################################

USER_ID = 'YOUR_USER_ID_HERE'
# Your PAT (Personal Access Token) can be found in the Account's Security section
PAT = 'YOUR_PAT_HERE'
APP_ID = 'YOUR_APP_ID_HERE'
# Change these to search by your own concepts
CONCEPT_ID = 'cat'

##########################################################################
# YOU DO NOT NEED TO CHANGE ANYTHING BELOW THIS LINE TO RUN THIS EXAMPLE
##########################################################################

from clarifai_grpc.channel.clarifai_channel import ClarifaiChannel
from clarifai_grpc.grpc.api import resources_pb2, service_pb2, service_pb2_grpc
from clarifai_grpc.grpc.api.status import status_code_pb2
from google.protobuf.struct_pb2 import Struct

channel = ClarifaiChannel.get_grpc_channel()
stub = service_pb2_grpc.V2Stub(channel)

metadata = (('authorization', 'Key ' + PAT),)

userDataObject = resources_pb2.UserAppIDSet(user_id=USER_ID, app_id=APP_ID) # The userDataObject is required when using a PAT

search_metadata = Struct()
search_metadata.update({"type": "animal"})

post_annotations_searches_response = stub.PostAnnotationsSearches(
    service_pb2.PostAnnotationsSearchesRequest(
        user_app_id=userDataObject,
        searches=[
            resources_pb2.Search(
                query=resources_pb2.Query(
                    filters=[
                        resources_pb2.Filter(
                            annotation=resources_pb2.Annotation(
                                data=resources_pb2.Data(metadata=search_metadata)
                            )
                        )
                    ],
                    ranks=[
                        resources_pb2.Rank(
                            annotation=resources_pb2.Annotation(
                                data=resources_pb2.Data(
                                    concepts=[  # You can search by multiple concepts.
                                        resources_pb2.Concept(
                                            id=CONCEPT_ID,  # You could search by concept Name as well.
                                            value=1,  # Value of 0 will search for images that don't have the concept.
                                        )
                                    ]
                                )
                            )
                        )
                    ],
                )
            )
        ],
        pagination=service_pb2.Pagination(per_page=2, page=1),
    ),
    metadata=metadata,
)

if post_annotations_searches_response.status.code != status_code_pb2.SUCCESS:
    raise Exception("Post searches failed, status: " + post_annotations_searches_response.status.description)

print("Search result:")
for hit in post_annotations_searches_response.hits:
    print("\tScore %.2f for annotation: %s off input: %s" % (hit.score, hit.annotation.id, hit.input.id))
```

### Negate Search Criteria

You can find all the data that is NOT similar to a given criteria.

- Python (gRPC)
- JavaScript (REST)
- Node.js (gRPC)
- Java (gRPC)
- PHP (gRPC)
- cURL

USER_ID = 'YOUR_USER_ID_HERE'
# Your PAT (Personal Access Token) can be found in the Account's Security section
PAT = 'YOUR_PAT_HERE'
APP_ID = 'YOUR_APP_ID_HERE'
# Change this to search by your own concept
CONCEPT_NAME = 'cat'

from clarifai_grpc.channel.clarifai_channel import ClarifaiChannel
from clarifai_grpc.grpc.api import resources_pb2, service_pb2, service_pb2_grpc
from clarifai_grpc.grpc.api.status import status_code_pb2

channel = ClarifaiChannel.get_grpc_channel()
stub = service_pb2_grpc.V2Stub(channel)

metadata = (('authorization', 'Key ' + PAT),)

userDataObject = resources_pb2.UserAppIDSet(user_id=USER_ID, app_id=APP_ID) # The userDataObject is required when using a PAT

post_annotations_searches_response = stub.PostAnnotationsSearches(
    service_pb2.PostAnnotationsSearchesRequest(
        user_app_id=userDataObject,
        searches = [
            resources_pb2.Search(
                query=resources_pb2.Query(
                    filters=[
                        resources_pb2.Filter(
                            annotation=resources_pb2.Annotation(
                                data=resources_pb2.Data(
                                    concepts=[  # You can search by multiple concepts
                                        resources_pb2.Concept(
                                            name=CONCEPT_NAME,  # You could search by concept id as well
                                        )
                                    ]
                                )
                            , negate=True)
                        )
                    ]
                )
            )
        ]
    ),
    metadata=metadata
)

if post_annotations_searches_response.status.code != status_code_pb2.SUCCESS:
    print(post_annotations_searches_response.status)
    raise Exception("Post searches failed, status: " + post_annotations_searches_response.status.description)

### Find Duplicate Images in Dataset

Here's how you can use the `PostInputsSearches` endpoint to identify near-duplicate images within a given dataset. You can also use the `min_value` threshold parameter to refine the search results, ensuring that only images surpassing a specified minimum probability resemblance score are included in the output. .

- cURL

```bash
curl -X POST "https://api.clarifai.com/v2/users/YOUR_USER_ID_HERE/apps/YOUR_APP_ID_HERE/inputs/searches" \ 
  -H "Authorization: Key YOUR_PAT_HERE" \ 
  -H "Content-Type: application/json" \ 
  -d '{
    "searches": [
      {
        "query": {
          "filters": [
            {
              "input": {
                "dataset_ids": ["YOUR_DATASET_ID_HERE"]
              }
            }
          ],
          "ranks": [
            {
              "annotation": {
                "data": {
                  "image": {
                    "url": "https://samples.clarifai.com/metro-north.jpg"
                  }
                }
              }
            }
          ]
        },
        "min_value": 0.95
      }
    ]
  }'
```

- [OR Search Operation](https://docs.clarifai.com/create/search/api/combine-negate/#or-search-operation)
- [AND Search Operation](https://docs.clarifai.com/create/search/api/combine-negate/#and-search-operation)
- [Combine Filter and Rank](https://docs.clarifai.com/create/search/api/combine-negate/#combine-filter-and-rank)
- [Combine Filter by Metadata and Rank](https://docs.clarifai.com/create/search/api/combine-negate/#combine-filter-by-metadata-and-rank)
- [Negate Search Criteria](https://docs.clarifai.com/create/search/api/combine-negate/#negate-search-criteria)
- [Find Duplicate Images in Dataset](https://docs.clarifai.com/create/search/api/combine-negate/#find-duplicate-images-in-dataset)
