title: Redis Data Modeling for Many-To-Many relationship
body: <p>Looking at the link - <a href="https://stackoverflow.com/questions/10907942/how-to-have-relations-many-to-many-in-redis">how to have relations many to many in redis</a>. I tried to model this using Spring Data Redis <code>HashRedis</code> class. This example model....</p>
  
  <pre><code># Here are my categories
  &gt; hmset category:1 name cinema  ... more fields ...
  &gt; hmset category:2 name music   ... more fields ...
  &gt; hmset category:3 name sports  ... more fields ...
  &gt; hmset category:4 name nature  ... more fields ...
  
  # Here are my users
  &gt; hmset user:1 name Jack   ... more fields ...
  &gt; hmset user:2 name John   ... more fields ...
  &gt; hmset user:3 name Julia  ... more fields ...
  
  # Let's establish the many-to-many relationship
  # Jack likes cinema and sports
  # John likes music and nature
  # Julia likes cinema, music and nature
  
  # For each category, we keep a set of reference on the users
  &gt; sadd category:1:users 1 3
  &gt; sadd category:2:users 2 3
  &gt; sadd category:3:users 1
  &gt; sadd category:4:users 2 3
  
  # For each user, we keep a set of reference on the categories
  &gt; sadd user:1:categories 1 3
  &gt; sadd user:2:categories 2 4
  &gt; sadd user:3:categories 1 2 4
  </code></pre>
  
  <p>Once we have this data structure, it is easy to query it using the set algebra:</p>
  
  <h1>Categories of Julia</h1>
  
  <pre><code>&gt; smembers user:3:categories
  1) "1"
  2) "2"
  3) "4"
  
  # Users interested by music
  &gt; smembers category:2:users
  1) "2"
  2) "3"
  
  # Users interested by both music and cinema
  &gt; sinter category:1:users category:2:users
  1) "3"
  </code></pre>
  
  <p>User.java</p>
  
  <pre><code>@Data
  @AllArgsConstructor
  @NoArgsConstructor
  @Builder
  @RedisHash("users")
  public class User {
      @Id
      private String userId;
      private String firstName;
      private String emailId;
      private List&lt;Category&gt; categories;
  }
  </code></pre>
  
  <p>Category.java</p>
  
  <pre><code>@Data
  @AllArgsConstructor
  @NoArgsConstructor
  @Builder
  @RedisHash("category")
  public class Category {
      @Id
      private String categoryId;
      private String name;
      private String type;
  
      private List&lt;User&gt; users;
  }
  </code></pre>
  
  <p>RedisExampleBootApplication.java</p>
  
  <pre><code>@SpringBootApplication
  public class RedisExampleBootApplication implements CommandLineRunner{
      @Autowired CategoryRepository categoryRepository;
      @Autowired UserRepository userRepository;
  
      public static void main(String[] args) {
          SpringApplication.run(RedisExampleBootApplication.class, args);
      }
  
      @Override
      public void run(String... args) throws Exception {  
  
          User jack = User.builder().firstName("Jack").emailId("jack@gmail.com").build();
          User john = User.builder().firstName("John").emailId("john@gmail.com").build();
          User julia  = User.builder().firstName("Julia ").emailId("julia @gmail.com").build();
  
          Category cinema = Category.builder().name("Cinema").type("Entertainment").users(Arrays.asList(jack, julia)).build();
          Category sports = Category.builder().name("Sports").type("Play Game").users(Arrays.asList(jack)).build();
  
          Category music = Category.builder().name("Music").type("Sounds").users(Arrays.asList(john, julia)).build();
          Category nature = Category.builder().name("Nature").type("Wild Life").users(Arrays.asList(john, julia)).build();
  
          categoryRepository.save(cinema);
          categoryRepository.save(sports);
          categoryRepository.save(music);
          categoryRepository.save(nature);
  
  
  
          Category myCinema = Category.builder().name("Cinema").name("Entertainment").build();
          Category mySport = Category.builder().name("Sports").name("Play Game").build();
          Category myMusic = Category.builder().name("Music").name("Sound").build();
          Category myNature = Category.builder().name("Nature").name("Wild Life").build();
  
  
          User myJack = User.builder().firstName("Jack").emailId("jack@gmail.com").categories(Arrays.asList(myCinema, mySport)).build();
          User myJohn = User.builder().firstName("John").emailId("john@gmail.com").categories(Arrays.asList(myMusic, myNature)).build();
          User myJulia  = User.builder().firstName("Julia ").emailId("julia @gmail.com").categories(Arrays.asList(myCinema,myMusic, myNature)).build();
  
          userRepository.save(myJack);
          userRepository.save(myJohn);
          userRepository.save(myJulia);
      }
  }
  </code></pre>
  
  <p>Here is the result of Data Modeling</p>
  
  <pre><code>127.0.0.1:6379&gt; KEYS *
  1) "category:0bcba339-9a3e-46e3-b33c-877f8d15595f"
  2) "category:4d2b8d10-83de-41fa-8a33-93f30a6f9ffc"
  3) "category:f756f18c-53e4-4a20-9a42-ad08b537f380"
  4) "category"
  5) "users:644d0adc-f0cf-4ba1-8d6b-d6f47145e5e7"
  6) "users:8aa5c578-4e05-4ae9-8f80-d10b789e0877"
  7) "users:825ab11b-803a-4e4f-a72d-e6b42b98007c"
  8) "category:54a56102-5836-41bf-86a8-c82b3f12d3cf"
  9) "users"
  127.0.0.1:6379&gt;
  </code></pre>
  
  <p>I've not used <code>@Indexed</code> anywhere, because currently I am not using any <code>findBy</code> method, but thats not the issue. I just need confirmation on how to model the data? Or POJO modelling is correct ?</p>
  
  <blockquote>
    <p>HGETALL users:8aa5c578-4e05-4ae9-8f80-d10b789e0877</p>
  </blockquote>
  
  <pre><code>userId 8aa5c578-4e05-4ae9-8f80-d10b789e0877
  _class com.example.model.User
  firstName Jack
  emailId jack@gmail.com
  categories.[1].name Play Game
  categories.[0].name Entertainment
  </code></pre>