Home > other >  Filter IndexedEmbedded entity in hiberenate search 6
Filter IndexedEmbedded entity in hiberenate search 6

Time:09-30

Let's say i have a Indexed entity User that IndexedEmbedded a list of Entity Role. In that list we have also past Roles (soft deleted), i wanna index User, end limit roles list to only active roles in my index.

Kind of:

@Entity
@Indexed
public class User{
  @FullTextField
  String name
  @IndexedEmbedded
  List<Role> roles
}

public class Role{
  @FullTextField
  String name
  String status //wanna filter status == "DELETED"
}

There is something like RoutingBridge in indexed annotation?

CodePudding user response:

First, a warning: you'd probably want to consider cleaning up associations upon soft-deletion of a role (remove the role from users), because this situation is likely to affect other parts of your application.

With that out of the way, here's a more useful answer...


No, RoutingBridge won't help here.

There's no built-in feature for what you're trying to achieve (yet).

The simplest solution I can think of is adding a "derived" getter that does the filtering.

@Entity
@Indexed
public class User{
  @FullTextField
  private String name;
  @ManyToMany
  private List<Role> roles;


  @javax.persistence.Transient
  @IndexedEmbedded(name = "roles")
  // Tell Hibernate Search that changing the status of a Role might
  // require reindexing
  @IndexingDependency(derivedFrom = @ObjectPath( 
      @PropertyValue(propertyName = "roles"), @PropertyValue(propertyName = "status")
  ))
  // Tell Hibernate Search how to find users to reindex
  // when a Role changes (its name or status)
  @AssociationInverseSide(inversePath = @ObjectPath(
      @PropertyValue(propertyName = "users")
  ))
  public List<Role> getNonDeletedRoles() {
    return roles.stream().filter(r -> !"DELETED".equals(r.getStatus()))
        .collect(Collectors.toList());
  }
}

@Entity
public class Role{
  @FullTextField
  private String name;
  private String status;
  // You will need this!
  @ManyToMany(mappedBy = "roles")
  private List<User> users;
}

If for some reason you cannot afford to model the association Role => User, you will have to give up on reindexing users when a role changes:

@Entity
@Indexed
public class User{
  @FullTextField
  private String name;
  @ManyToMany
  private List<Role> roles;

  @javax.persistence.Transient
  @IndexedEmbedded(name = "roles")
  @IndexingDependency(reindexOnUpdate = ReindexOnUpdate.SHALLOW,
      derivedFrom = @ObjectPath(@PropertyValue(propertyName = "roles")))
  public List<Role> getNonDeletedRoles() {
    return roles.stream().filter(r -> !"DELETED".equals(r.getStatus()))
        .collect(Collectors.toList());
  }
}

@Entity
public class Role{
  @FullTextField
  private String name;
  private String status;
}
  • Related