• Stars
    star
    599
  • Rank 74,745 (Top 2 %)
  • Language
    Java
  • License
    MIT License
  • Created about 3 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Spring Data Redis extensions for better search, documents models, and more


Redis OM

Object Mapping (and more) for Redis!


Redis OM Spring extends Spring Data Redis to take full advantage of the power of Redis.

Stage Release Snapshot Issues Resolution Code QL License SDR Ver.
Project stage Releases Snapshots Percentage of issues still open Average time to resolve an issue CodeQL License SDR Version

Learn / Discuss / Collaborate

Discord Twitch YouTube Twitter
Discord Twitch YouTube Twitter
Table of contents

๐Ÿ’ก Why Redis OM?

The Redis OM family of projects aim is to provide high-level abstractions idiomatically implemented for your language/platform of choice. We currently cater to the Node, Python, .Net and Spring communities.

๐Ÿ€ Redis OM Spring

Redis OM Spring provides powerful repository and custom object-mapping abstractions built on top of the powerful Spring Data Redis (SDR) framework.

This preview release provides all of SDRs capabilities plus:

  • @Document annotation to map Spring Data models to Redis JSON documents
  • Enhances SDRs @RedisHash via @EnableRedisEnhancedRepositories to:
    • uses Redis' native search engine (RediSearch) for secondary indexing
    • uses ULID for @Id annotated fields
  • RedisDocumentRepository with automatic implementation of Repository interfaces for complex querying capabilities using @EnableRedisDocumentRepositories
  • Declarative Search Indices via @Indexed
  • Full-text Search Indices via @Searchable
  • EntityStreams: Streams-based Query and Aggregations Builder
  • @Bloom annotation to determine very fast, with and with high degree of certainty, whether a value is in a collection.
  • @Vectorize annotation to generate embeddings for text and images for use in Vector Similarity Searches
  • Vector Similarity Search API (See Redis Stack Vectors)

Note: Redis OM Spring depends on Jedis.

๐Ÿ Getting Started

Here is a quick teaser of an application using Redis OM Spring to map a Spring Data model using a RedisJSON document.

๐Ÿš€ Launch Redis

Redis OM Spring relies on the power of the RediSearch and RedisJSON modules. Before writing any code you'll need a Redis instance with the appropriate Redis modules! The quickest way to get this is with Docker:

docker run -p 6379:6379 -p 8001:8001 redis/redis-stack

This launches the redis-stack an extension of Redis that adds all manner of modern data structures to Redis. You'll also notice that if you open up http://localhost:8001 you'll have access to the redis-insight GUI, a GUI you can use to visualize and work with your data in Redis. We have also provided a docker compose YAML file for you to quickly get started using Redis Stack.

To launch the docker compose application, on the command line (or via Docker Desktop), clone this repository and run (from the root folder):

docker compose up

Configuring your Redis Connection

By default, Redis OM Spring connects to localhost at port 6379. If your instance is running somewhere else, you can configure the connection in your application.properties or application.yaml:

In applications.properties:

spring.data.redis.host=your.cloud.db.redislabs.com                                                                                                                                                                                                                    |
spring.data.redis.port=12345
spring.data.redis.password=xxxxxxxx
spring.data.redis.username=default

In applications.yaml:

spring:
  data:
    redis:
      host: your.cloud.db.redislabs.com
      port: 12345
      password: xxxxxxxx
      username: default

The SpringBoot App

Use the @EnableRedisDocumentRepositories annotation to scan for @Document annotated Spring models, Inject repositories beans implementing RedisDocumentRepository which you can use for CRUD operations and custom queries (all by declaring Spring Data Query Interfaces):

package com.redis.om.documents;

import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.geo.Point;

import com.redis.om.documents.domain.Company;
import com.redis.om.documents.repositories.CompanyRepository;

@SpringBootApplication
@Configuration
@EnableRedisDocumentRepositories(basePackages = "com.redis.om.documents.*")
public class RomsDocumentsApplication {

  @Autowired
  CompanyRepository companyRepo;

  @Bean
  CommandLineRunner loadTestData() {
    return args -> {
      // remove all companies
      companyRepo.deleteAll();

      // Create a couple of `Company` domain entities
      Company redis = Company.of(
        "Redis", "https://redis.com", new Point(-122.066540, 37.377690), 526, 2011 //
      );
      redis.setTags(Set.of("fast", "scalable", "reliable"));

      Company microsoft = Company.of(
        "Microsoft", "https://microsoft.com", new Point(-122.124500, 47.640160), 182268, 1975 //
      );
      microsoft.setTags(Set.of("innovative", "reliable"));

      // save companies to the database
      companyRepo.save(redis);
      companyRepo.save(microsoft);
    };
  }

  public static void main(String[] args) {
    SpringApplication.run(RomsDocumentsApplication.class, args);
  }
}

๐Ÿ’โ€โ™‚๏ธ The Mapped Model

Like many other Spring Data projects, an annotation at the class level determines how instances of the class are persisted. Redis OM Spring provides the @Document annotation to persist models as JSON documents using RedisJSON:

package com.redis.om.documents.domain;

import java.util.HashSet;
import java.util.Set;

import org.springframework.data.annotation.Id;
import org.springframework.data.geo.Point;
import com.redis.om.spring.annotations.Document;
import com.redis.om.spring.annotations.Searchable;
import lombok.*;

@Data @NoArgsConstructor @RequiredArgsConstructor(staticName = "of") @AllArgsConstructor(access = AccessLevel.PROTECTED) @Document public class Company {
  @Id private String id;
  @Searchable private String name;
  @Indexed private Point location;
  @Indexed private Set<String> tags = new HashSet<>();
  @Indexed private Integer numberOfEmployees;
  @Indexed private Integer yearFounded;
  private String url;
  private boolean publiclyListed;

  // ...
}

Redis OM Spring, replaces the conventional UUID primary key strategy generation with a ULID (Universally Unique Lexicographically Sortable Identifier) which is faster to generate and easier on the eyes.

๐Ÿงฐ The Repository

Redis OM Spring data repository's goal, like other Spring Data repositories, is to significantly reduce the amount of boilerplate code required to implement data access. Simply create a Java interface that extends RedisDocumentRepository that takes the domain class to manage as well as the ID type of the domain class as type arguments. RedisDocumentRepository extends the Spring Data class PagingAndSortingRepository.

Declare query methods on the interface. You can both, expose CRUD methods or create declarations for complex queries that Redis OM Spring will fulfill at runtime:

package com.redis.om.documents.repositories;

import java.util.*;

import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Point;
import org.springframework.data.repository.query.Param;

import com.redis.om.documents.domain.Company;
import com.redis.om.spring.annotations.Query;
import com.redis.om.spring.repository.RedisDocumentRepository;

public interface CompanyRepository extends RedisDocumentRepository<Company, String> {
  // find one by property
  Optional<Company> findOneByName(String name);

  // geospatial query
  Iterable<Company> findByLocationNear(Point point, Distance distance);

  // find by tag field, using JRediSearch "native" annotation
  @Query("@tags:{$tags}")
  Iterable<Company> findByTags(@Param("tags") Set<String> tags);

  // find by numeric property
  Iterable<Company> findByNumberOfEmployees(int noe);

  // find by numeric property range
  Iterable<Company> findByNumberOfEmployeesBetween(int noeGT, int noeLT);

  // starting with/ending with
  Iterable<Company> findByNameStartingWith(String prefix);
}

The repository proxy has two ways to derive a store-specific query from the method name:

  • By deriving the query from the method name directly.
  • By using a manually defined query using the @Query or @Aggregation annotations.

๐Ÿšค Querying with Entity Streams

Redis OM Spring Entity Streams provides a Java 8 Streams interface to Query Redis JSON documents using RediSearch. Entity Streams allow you to process data in a type safe declarative way similar to SQL statements. Streams can be used to express a query as a chain of operations.

Entity Streams in Redis OM Spring provides the same semantics as Java 8 streams. Streams can be made of Redis Mapped entities (@Document) or one or more properties of an Entity. Entity Streams progressively build the query until a terminal operation is invoked (such as collect). Whenever a Terminal operation is applied to a Stream, the Stream cannot accept additional operations to its pipeline and it also means that the Stream is started.

Let's start with a simple example, a Spring @Service which includes EntityStream to query for instances of the mapped class Person:

package com.redis.om.skeleton.services;

import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.redis.om.skeleton.models.Person;
import com.redis.om.skeleton.models.Person$;
import com.redis.om.spring.search.stream.EntityStream;

@Service
public class PeopleService {
  @Autowired
  EntityStream entityStream;

  // Find all people
  public Iterable<Person> findAllPeople() {
    return entityStream //
        .of(Person.class) //
        .collect(Collectors.toList());
  }

}

The EntityStream is injected into the PeopleService using @Autowired. We can then get a stream for Person objects by using entityStream.of(Person.class). At this point the stream represents the equivalent of a SELECT * FROM Person on a relational database. The call to collect will then execute the underlying query and return a collection of all Person objects in Redis.

๐Ÿ‘ญ Entity Meta-model

To produce more elaborate queries, you're provided with a generated metamodel, which is a class with the same name as your model but ending with a dollar sign. In the example below, our entity model is Person therefore we get a metamodel named Person$. With the metamodel you have access to the operations related to the underlying search engine field. For example, in the example we have an age property which is an integer. Therefore, our metamodel has an AGE property which has numeric operations we can use with the stream's filter method such as between.

// Find people by age range
public Iterable<Person> findByAgeBetween(int minAge, int maxAge) {
  return entityStream //
      .of(Person.class) //
      .filter(Person$.AGE.between(minAge, maxAge)) //
      .sorted(Person$.AGE, SortOrder.ASC) //
      .collect(Collectors.toList());
}

In this example we also make use of the Streams sorted method to declare that our stream will be sorted by the Person$.AGE in ASCending order.

Check out the full set of tests for EntityStreams

๐Ÿ‘ฏโ€๏ธ Querying by Example (QBE)

Query by Example (QBE) is a user-friendly querying technique with a simple interface. It allows dynamic query creation and does not require you to write queries that contain field names. In fact, Query by Example does not require you to write queries by using store-specific query languages at all.

QBE Usage

The Query by Example API consists of four parts:

  • Probe: The actual example of a domain object with populated fields.
  • ExampleMatcher: The ExampleMatcher carries details on how to match particular fields. It can be reused across multiple Examples.
  • Example: An Example consists of the probe and the ExampleMatcher. It is used to create the query.
  • FetchableFluentQuery: A FetchableFluentQuery offers a fluent API, that allows further customization of a query derived from an Example. Using the fluent API lets you specify ordering projection and result processing for your query.

Query by Example is well suited for several use cases:

  • Querying your data store with a set of static or dynamic constraints.
  • Frequent refactoring of the domain objects without worrying about breaking existing queries.
  • Working independently of the underlying data store API.

For example, if you have an @Document or @RedisHash annotated entity you can create an instance, partially populate its properties, create an Example from it, and used the findAll method to query for similar entities:

MyDoc template = new MyDoc();
template.setTitle("hello world");
template.setTag(Set.of("artigo"));

Example<MyDoc> example = Example.of(template, ExampleMatcher.matchingAny());

Iterable<MyDoc> allMatches = repository.findAll(example);

๐Ÿ’ป Maven configuration

Official Releases

<dependency>
  <groupId>com.redis.om</groupId>
  <artifactId>redis-om-spring</artifactId>
  <version>${version}</version>
</dependency>

Explicitly configuring OM as an annotation processor

For Maven, things normally just work, when you run ./mvnw spring-boot:run. Some users have experienced this not being the case, in which I recommend to explicitly declaring the maven-compiler-plugin in the case below it is paired with an app created with start.spring.io with Spring Boot v3.0.4 (all other versions can be inherited from the parent poms):

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>${maven-compiler-plugin.version}</version>
  <configuration>
    <annotationProcessorPaths>
      <path>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <version>3.1.2</version>
      </path>
      <path>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${lombok.version}</version>
      </path>
      <path>
        <groupId>com.redis.om</groupId>
        <artifactId>redis-om-spring</artifactId>
        <version>0.8.7-SNAPSHOT</version>
      </path>
    </annotationProcessorPaths>
  </configuration>
</plugin>

Snapshots

  <repositories>
    <repository>
      <id>snapshots-repo</id>
      <url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
    </repository>
  </repositories>

and

<dependency>
  <groupId>com.redis.om</groupId>
  <artifactId>redis-om-spring</artifactId>
  <version>${version}-SNAPSHOT</version>
</dependency>

Ready to learn more? Check out the getting started guide.

๐Ÿ˜ Gradle configuration

Add Repository - Snapshots Only

repositories {
    mavenCentral()
    maven {
        url 'https://s01.oss.sonatype.org/content/repositories/snapshots/'
    }
}

Dependency

ext {
  redisOmVersion = '0.8.7-SNAPSHOT'
}

dependencies {
  implementation "com.redis.om:redis-om-spring:$redisOmVersion"
  annotationProcessor "com.redis.om:redis-om-spring:$redisOmVersion"
}

๐Ÿ“š Documentation

The Redis OM documentation is available here.

Demos

Embedded Demos

These can be found in the /demos folder:

  • roms-documents:

    • Simple API example of @Document mapping, Spring Repositories and Querying.
    • Run with ./mvnw install -Dmaven.test.skip && ./mvnw spring-boot:run -pl demos/roms-documents
  • roms-hashes:

    • Simple API example of @RedisHash, enhanced secondary indices and querying.
    • Run with ./mvnw install -Dmaven.test.skip && ./mvnw spring-boot:run -pl demos/roms-hashes
  • roms-permits:

    • Port of Elena Kolevska's Quick Start: Using RediSearch with JSON [Demo][redisearch-wjso] to Redis OM Spring.
    • Run with ./mvnw install -Dmaven.test.skip && ./mvnw spring-boot:run -pl demos/roms-permits
  • roms-vss:

    • Port of Redis Vector Search Demo.
    • Run with ./mvnw install -Dmaven.test.skip && ./mvnw spring-boot:run -pl demos/roms-vss

External Demos

โ›๏ธ Troubleshooting

If you run into trouble or have any questions, we're here to help!

First, check the FAQ. If you don't find the answer there, hit us up on the Redis Discord Server.

โœจ So How Do You Get RediSearch and RedisJSON?

Redis OM relies on two source available Redis modules: RediSearch and RedisJSON.

You can run these modules in your self-hosted Redis deployment, or you can use Redis Enterprise, which includes both modules.

To learn more, read our documentation.

๐Ÿ’– Contributing

We'd love your contributions!

Bug reports are especially helpful at this stage of the project. You can open a bug report on GitHub.

You can also contribute documentation -- or just let us know if something needs more detail. Open an issue on GitHub to get started.

๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘ Sibling Projects

๐Ÿ“ License

Redis OM uses the MIT license.

More Repositories

1

redis

Redis is an in-memory database that persists on disk. The data model is key-value, but many different kind of values are supported: Strings, Lists, Sets, Sorted Sets, Hashes, Streams, HyperLogLogs, Bitmaps.
C
66,875
star
2

go-redis

Redis Go client
Go
19,891
star
3

node-redis

Redis Node.js client
TypeScript
16,841
star
4

ioredis

๐Ÿš€ A robust, performance-focused, and full-featured Redis client for Node.js.
TypeScript
14,344
star
5

redis-py

Redis Python client
Python
12,506
star
6

jedis

Redis Java client
Java
11,766
star
7

hiredis

Minimalistic C client for Redis >= 1.2
C
6,197
star
8

lettuce

Advanced Java Redis client for thread-safe sync, async, and reactive usage. Supports Cluster, Sentinel, Pipelining, and codecs.
Java
5,352
star
9

redis-rb

A Ruby client library for Redis
Ruby
3,963
star
10

rueidis

A fast Golang Redis client that supports Client Side Caching, Auto Pipelining, Generics OM, RedisJSON, RedisBloom, RediSearch, etc.
Go
2,327
star
11

redis-doc

Redis documentation source code for markdown and metadata files, conversion scripts, and so forth
Shell
2,310
star
12

redis-om-node

Object mapping, and more, for Redis and Node.js. Written in TypeScript.
TypeScript
1,158
star
13

docker-library-redis

Docker Official Image packaging for Redis
Shell
1,117
star
14

redis-om-python

Object mapping, and more, for Redis and Python
Python
1,093
star
15

redis-io

Application running http://redis.io
Ruby
637
star
16

hiredis-py

Python wrapper for hiredis
C
495
star
17

redis-om-dotnet

Object mapping, and more, for Redis and .NET
C#
457
star
18

hiredis-rb

Ruby wrapper for hiredis
Ruby
319
star
19

hiredis-node

Node wrapper for hiredis
JavaScript
305
star
20

riot

๐Ÿงจ Get data in & out of Redis with RIOT
Java
273
star
21

NRedisStack

Redis Stack .Net client
C#
220
star
22

redis-vl-python

Redis Vector Library (RedisVL) interfaces with Redis' vector database for realtime semantic search, RAG, and recommendation systems.
Python
218
star
23

redis-rcp

Redis Change Proposals
136
star
24

redis-hashes

Redis tarball SHA1 hashes
92
star
25

lettucemod

Java client for Redis Modules
Java
50
star
26

spring-batch-redis

Spring Batch extension for Redis
Java
47
star
27

redis-specifications

A bin for Redis' specs
38
star
28

minipilot

MiniPilot is a GenAI-assisted chatbot backed by Redis. Chat with your documents
HTML
31
star
29

redis-benchmarks-specification

The Redis benchmarks specification describes the cross-language/tools requirements and expectations to foster performance and observability standards around redis related technologies. Members from both industry and academia, including organizations and individuals are encouraged to contribute.
Python
29
star
30

librdb

Redis RDB file parser, with JSON, RESP and RDB-loader extensions
C
23
star
31

docs

Documentation for Redis, Redis Cloud, and Redis Enterprise
Python
23
star
32

redis-debian

Debian packaging
Shell
18
star
33

redis-snap

A repository for snap packaging
10
star
34

redis-website

HTML
9
star
35

Redis-Insight-Guides

Learn modern data models and data processing tools bundled in Redis Stack to build real-time applications with the speed and stability of Redis.
5
star
36

redis-clinterwebz

Python
4
star
37

redis-extra-ci

4
star
38

riot-docker

Dockerfile
2
star
39

redis-rpm

Shell
2
star
40

scoop

1
star
41

homebrew-tap

Homebrew tap for Redis organization
Ruby
1
star