Tuesday, 9 September 2025

Filtering Embedding Searches in LangChain4j

When working with large-scale vector databases like Pinecone, Milvus, or Qdrant, semantic search isn't just about finding similar embeddings, it's about finding the right similar items. Just like SQL how we can filter rows using WHERE clauses, modern vector databases also support metadata based filtering. LangChain4j abstracts over multiple vector stores, and its Filter API enables a consistent way to define these filters.

In this post, we’ll explore how to use Filter in LangChain4j to refine your embedding searches using rich metadata, and the types of filters available.

 

Why Filtering Matters in Vector Search?

Imagine a movie recommendation system. You don't just want "similar" movies, you want similar comedies, released after 2010, and with a rating above 7. That’s where metadata filtering becomes essential.

 

LangChain4j provides an expressive API to define filters that work across multiple embedding store implementations. These filters operate on metadata fields associated with each embedding.

 

Following table summarizes the list of filters available in LangChain4j.

Filter Type

Description

IsEqualTo

Checks if metadata key equals a given value

IsNotEqualTo

Opposite of IsEqualTo

IsGreaterThan

Numerical comparison

IsGreaterThanOrEqualTo

Numerical comparison

IsLessThan

Numerical comparison

IsLessThanOrEqualTo

Numerical comparison

IsIn

Checks if a value is in a given set/list

IsNotIn

Checks if a value is not in a given set/list

ContainsString

Checks if string contains a substring (limited support)

And, Or, Not

Logical combinators to build complex expressions

 

Example 

Filter filter = new And(
	    new And(
	        new IsEqualTo("source", "news"),
	        new IsIn("category", List.of("technology", "finance"))
	    ),
	    new IsGreaterThanOrEqualTo("relevance", Integer.valueOf(9))
	);

Find the below working application.

 

EmbeddingSearchWithFilters.java

package com.sample.app.embeddings;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import dev.langchain4j.data.document.Metadata;
import dev.langchain4j.data.embedding.Embedding;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.embedding.onnx.bgesmallenv15q.BgeSmallEnV15QuantizedEmbeddingModel;
import dev.langchain4j.store.embedding.EmbeddingSearchRequest;
import dev.langchain4j.store.embedding.EmbeddingSearchResult;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.filter.Filter;
import dev.langchain4j.store.embedding.filter.comparison.IsEqualTo;
import dev.langchain4j.store.embedding.filter.comparison.IsGreaterThanOrEqualTo;
import dev.langchain4j.store.embedding.filter.comparison.IsIn;
import dev.langchain4j.store.embedding.filter.logical.And;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;

public class EmbeddingSearchWithFilters {

	public static void main(String[] args) {

		// Step 1: Initialize embedding model
		EmbeddingModel model = new BgeSmallEnV15QuantizedEmbeddingModel();

		// Step 2: Prepare text data with metadata
		String sentence1 = "The stock market surged as tech companies reported strong earnings.";
		Map<String, Object> metaMap1 = new HashMap<>();
		metaMap1.put("category", "finance");
		metaMap1.put("source", "news");
		metaMap1.put("relevance", 9);
		Metadata meta1 = Metadata.from(metaMap1);

		String sentence2 = "Tech giants like Apple and Amazon saw record profits this quarter.";
		Map<String, Object> metaMap2 = new HashMap<>();
		metaMap2.put("category", "technology");
		metaMap2.put("source", "news");
		metaMap2.put("relevance", 10);
		Metadata meta2 = Metadata.from(metaMap2);

		String sentence3 = "Heavy rain caused flooding in coastal towns yesterday.";
		Map<String, Object> metaMap3 = new HashMap<>();
		metaMap3.put("category", "weather");
		metaMap3.put("source", "alert");
		metaMap3.put("relevance", 5);
		Metadata meta3 = Metadata.from(metaMap3);

		try {
			// Step 3: Generate embeddings
			Embedding embedding1 = model.embed(sentence1).content();
			Embedding embedding2 = model.embed(sentence2).content();
			Embedding embedding3 = model.embed(sentence3).content();

			// Step 4: Initialize in-memory embedding store
			EmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();

			// Step 5: Add embeddings to the store with metadata
			embeddingStore.add(embedding1, TextSegment.from(sentence1, meta1));
			embeddingStore.add(embedding2, TextSegment.from(sentence2, meta2));
			embeddingStore.add(embedding3, TextSegment.from(sentence3, meta3));

			System.out.println("Embeddings with metadata added to the store successfully.");

			// Step 6: Prepare a query embedding
			Embedding queryEmbedding = model.embed("Which tech companies had profits?").content();

			Filter filter = new And(
					new And(new IsEqualTo("source", "news"), new IsIn("category", List.of("technology", "finance"))),
					new IsGreaterThanOrEqualTo("relevance", Integer.valueOf(9)));

			// Step 8: Build search request with filter
			EmbeddingSearchRequest request = EmbeddingSearchRequest.builder().queryEmbedding(queryEmbedding)
					.maxResults(2).minScore(0.5).filter(filter).build();

			// Step 9: Perform search
			EmbeddingSearchResult<TextSegment> result = embeddingStore.search(request);

			// Step 10: Display results
			System.out.println("\nFiltered & Ranked Results:");
			result.matches().forEach(match -> {
				TextSegment segment = match.embedded();
				System.out.printf("Score: %.3f | Text: %s | Metadata: %s%n", match.score(), segment.text(),
						segment.metadata());
			});

		} catch (Exception e) {
			System.err.println("An error occurred: " + e.getMessage());
			e.printStackTrace();
		}
	}
}

Output

Embeddings with metadata added to the store successfully.

Filtered & Ranked Results:
Score: 0.883 | Text: Tech giants like Apple and Amazon saw record profits this quarter. | Metadata: Metadata { metadata = {category=technology, relevance=10, source=news} }
Score: 0.882 | Text: The stock market surged as tech companies reported strong earnings. | Metadata: Metadata { metadata = {category=finance, relevance=9, source=news} }

 

Previous                                                    Next                                                    Home

No comments:

Post a Comment