How to search for text and filter?

493 views Asked by At

UPDATE: This is fixed in 0.8.0

I am trying to search for filter by an indexed field and search for free text inside my objects. It seems that it is searching for the company name or the search term. How do I make this an and for SearchStream.freeText(String freeText)?

I need to use SearchStream.freeText since there are many fields I want to search on.

My data based on the roms-documents, I modified RomsDocumentsApplication

companyRepo.deleteAll();
Company redis1 = Company.of("Redis", "wwwabccom", new Point(-122.066540, 37.377690), 526, 2011, Set.of(CompanyMeta.of("Redis", 100, Set.of("RedisTag"))));
Company redis2 = Company.of("Redis", "wwwxyzcom", new Point(-122.066540, 37.377690), 526, 2011, Set.of(CompanyMeta.of("Redis", 100, Set.of("RedisTag"))));

Company microsoft1 = Company.of("Microsoft", "wwwabcnet", new Point(-122.066540, 37.377690), 526, 2011, Set.of(CompanyMeta.of("Redis", 100, Set.of("RedisTag"))));
Company microsoft2 = Company.of("Microsoft", "wwwxyznet", new Point(-122.066540, 37.377690), 526, 2011, Set.of(CompanyMeta.of("Redis", 100, Set.of("RedisTag"))));


companyRepo.save(redis1);
companyRepo.save(redis2);
companyRepo.save(microsoft1);
companyRepo.save(microsoft2);


@Data
@NoArgsConstructor
@RequiredArgsConstructor(staticName = "of")
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@Document
@ToString
public class Company {
  @Id
  private String id;

  @NonNull
  @Indexed
  private String name;

If I search, my first two searches seem fine, but my third search find values not for the company Microsoft, but for Redis

var result1 = entityStream.of(Company.class)
        .filter(Company$.NAME.eq("Redis"))
        .filter("*abc*")
        .collect(Collectors.toList());
System.out.println("Search1:");
result1.forEach(System.out::println);

var result2 = entityStream.of(Company.class)
        .filter(Company$.NAME.eq("Microsoft"))
        .filter("*xyz*")
        .collect(Collectors.toList());
System.out.println("Search2:");
result2.forEach(System.out::println);

var result3 = entityStream.of(Company.class)
      .filter(Company$.NAME.eq("Microsoft"))
      .filter("*co*")
      .collect(Collectors.toList());
System.out.println("Search3:");
result3.forEach(System.out::println);

The output of the program:

Search1:

Company(id=01GR46XB7BMJXV5WK3AJ3FA4M9, name=Redis, tags=[], url=wwwabccom, Company(id=01GR46XB974C3JJDAW70N20SFV, name=Microsoft, tags=[], url=wwwabcnet,

Search2:

Company(id=01GR46XB9388CRW0P71QM45K43, name=Redis, tags=[], url=wwwxyzcom, Company(id=01GR46XB9ABBV3TN9BTQFP08C1, name=Microsoft, tags=[], url=wwwxyznet,

Search3:

Company(id=01GR46XB7BMJXV5WK3AJ3FA4M9, name=Redis, tags=[], url=wwwabccom, Company(id=01GR46XB9388CRW0P71QM45K43, name=Redis, tags=[], url=wwwxyzcom,

I start redis with

docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 redis/redis-stack:6.2.6-v2

module list

127.0.0.1:6379> module list
1) 1) "name"
   2) "timeseries"
   3) "ver"
   4) (integer) 10805
2) 1) "name"
   2) "graph"
   3) "ver"
   4) (integer) 21005
3) 1) "name"
   2) "ReJSON"
   3) "ver"
   4) (integer) 20403
4) 1) "name"
   2) "search"
   3) "ver"
   4) (integer) 20604
5) 1) "name"
   2) "bf"
   3) "ver"
   4) (integer) 20403

Maven

<dependency>
  <groupId>com.redis.om</groupId>
  <artifactId>redis-om-spring</artifactId>
  <version>0.6.4</version>
</dependency>
2

There are 2 answers

0
rjdkolb On BEST ANSWER

The answer is actually quite simple.

The order of the filter matters. If you search in this order the first filter is ignored.

var result3 = entityStream.of(Company.class)
      .filter(Company$.NAME.eq("Microsoft"))
      .filter("*co*")
      .collect(Collectors.toList());
System.out.println("Search3:");

If you switch the filter it works flawlessly

var result4 = entityStream.of(Company.class)
        .filter("*co*")
        .filter(Company$.NAME.eq("Microsoft"))
        .collect(Collectors.toList());
System.out.println("Search4:");
result4.forEach(System.out::println);

I found this out by placing a break point on io.redisearch.client.Client Somehow for Search3 the filter on Company name is missing, but is present for Search4.

Added a bug report.

1
BSB On

Can you post the output of modules list from the CLI? I suspect this has to do with Redis' rules for tokenization/Escaping https://redis.io/docs/stack/search/reference/escaping/ and prefix https://redis.io/docs/stack/search/reference/query_syntax/#prefix-matching and infix/suffix matches https://redis.io/docs/stack/search/reference/query_syntax/#infixsuffix-matching