Quantcast
Channel: Active questions tagged redis+java - Stack Overflow
Viewing all articles
Browse latest Browse all 2203

FT.SEARCH not working with cluster based Redis server configuration

$
0
0
  • Redis Version: 7.2.1
  • Installed Modules: RediSearch v.2.4.15, RedisJSON v.99.99.99
  • Number of nodes: xx.x.x.xxx:6379, xx.x.x.xxx:6380, xx.x.x.xxx:6381, xx.x.x.xxx:6382, xx.x.x.xxx:6383, xx.x.x.xxx:6384

pom.xml

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.2.3</version></dependency>

Configuration

@Beanpublic JedisCluster getRedisCluster() {     Set<HostAndPort> jedisClusterNode = new HashSet<>();    String[] nodes = {"xx.x.x.xxx:6379", "xx.x.x.xxx:6380", "xx.x.x.xxx:6381", "xx.x.x.xxx:6382", "xx.x.x.xxx:6383", "xx.x.x.xxx:6384"};   for (int i = 0; i < nodes.length; i++) {    String[] ipAndPort = nodes[i].split(":");    jedisClusterNode.add(new HostAndPort(ipAndPort[0], Integer.valueOf(ipAndPort[1])));   }  JedisCluster jc = new JedisCluster(jedisClusterNode, "default", "admin");  logger.debug("Redis(FT) connection Successfully.");  return jc;}

BookDataSearchIndex.java

@Component@Order(1)public class BookDataSearchIndex implements CommandLineRunner {    private static final Logger logger = LoggerFactory.getLogger(BookDataSearchIndex.class);    @Autowired    private UnifiedJedis jedis;    @Override    public void run(String... args) throws Exception {        try {            Schema schema = new Schema()                    .addField(new Schema.Field(FieldName.of("$.bookId").as("BOOKID"), Schema.FieldType.TEXT, false,                            false))                    .addField(new Schema.Field(FieldName.of("$.title").as("TITLE"), Schema.FieldType.TEXT, false, false))                    .addField(new Schema.Field(FieldName.of("$.price").as("PRICE"), Schema.FieldType.NUMERIC, true, false));            IndexDefinition indexDefinition = new IndexDefinition(IndexDefinition.Type.JSON)                    .setPrefixes("book:");            jedis.ftCreate("bookdata-idx", IndexOptions.defaultOptions().setDefinition(indexDefinition),                    schema);        } catch (Exception e) {            logger.debug("Inside run in BookDataSearchIndex : {}", e.getMessage());        }    }}

BookData.java

public class BookData {  private String bookId;  private String title;  private Long price;  // Setter & Getter}

Page.java

public class Page<T> {    private List<T> data;    private Integer totalPage;    private Integer currentPage;    private Long total;    public Page(List<T> data, Integer totalPage, Integer currentPage, Long total) {        super();        this.data = data;        this.totalPage = totalPage;        this.currentPage = currentPage;        this.total = total;    }    // Setter & Getter}

BookDataHelper.java

import java.lang.reflect.Field;import java.util.ArrayList;import java.util.Calendar;import java.util.Date;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Map.Entry;import java.util.stream.Collectors;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import com.google.gson.Gson;import redis.clients.jedis.UnifiedJedis;import redis.clients.jedis.search.Document;import redis.clients.jedis.search.Query;import redis.clients.jedis.search.SearchResult;public class BookDataHelper {    private static final String ATTHERATE = "@";    private static final String LESS_THEN = "lt";    private static final String GREATER_THEN_EQUAL = "gte";    private static final String GREATER_THEN = "gt";    private static final String LESS_THEN_EQUAL = "lte";    private static final String BETWEEN = "between";    private static final Logger logger = LoggerFactory.getLogger(BookDataHelper.class);    @Autowired    private UnifiedJedis jedis;    public BookData save(BookData data) {        String memberKey = "book:"+ data.getBookId();        Gson gson = new Gson();        jedis.jsonSet(getKey(memberKey), gson.toJson(data));        jedis.sadd(getKey("bookdata"), getKey(memberKey));        return data;    }    public BookData findByKey(String index, String key, Object value, Class<BookData> dto) {        Map<String, Object> fields = new HashMap<>();        fields.put(key, value);        List<BookData> t = search(index, fields, dto);        if (!t.isEmpty()) {            return t.get(0);        }        return null;    }    public List<BookData> search(String index, Map<String, Object> fields, Class<BookData> dto) {        String queryCriteria = buildQuery(dto, fields, null);        return buildResponse(index, queryCriteria, dto);    }    public Page<BookData> search(String index, String queryCriteria, Integer offset, Integer limit, Class<BookData> dto) {        Query query = null;        if (queryCriteria.isEmpty()) {            query = new Query();        } else {            query = new Query(queryCriteria);        }        query.limit(offset, limit);        SearchResult searchResult = jedis.ftSearch(index, query);        Long total = searchResult.getTotalResults();        int totalPage = (int) Math.ceil((double) total / limit);        List<BookData> orderDataList = searchResult.getDocuments().stream()                .map(document -> convertDocumentToModel(document, dto)).collect(Collectors.toList());        return new Page<>(orderDataList, totalPage, offset, total);    }    ////////////////////////////////////////////////////////////////////////////////////////////////////////    ////////                                 PRIVATE METHODS                                        ////////    ////////////////////////////////////////////////////////////////////////////////////////////////////////    private List<BookData> buildResponse(String index, String queryCriteria, Class<BookData> dto) {        int offset = 0;        int limit = 10;        boolean done = false;        List<BookData> result = new ArrayList<>();        while (!done) {            Page<BookData> pageResult = search(index, queryCriteria,offset, limit, dto);            result.addAll(pageResult.getData());            // Check if there are more pages of results            if (pageResult.getData().isEmpty() || pageResult.getTotal() < limit) {                done = true;            } else {                offset += limit;            }        }        return result;    }    private static synchronized String buildQuery(Class<?> dto, Map<String, Object> fields, Map<String, String> operators) {        StringBuilder queryBuilder = new StringBuilder();        List<String> entityNumberTypeFields = getNumberFields(dto);        for (Entry<String, Object> entry : fields.entrySet()) {            String fieldName = entry.getKey().trim().toUpperCase();            Object fieldValue = toValue(entry.getValue());            if (null != operators && operators.containsKey(entry.getKey().trim())) {                String operator = operators.get(entry.getKey().trim()).trim();                buildOperatorsQuery(queryBuilder, operator, fieldName, fieldValue, entry.getValue());            } else {                if(entityNumberTypeFields.contains(fieldName)) {                    queryBuilder.append(ATTHERATE).append(fieldName).append(":[").append(fieldValue).append(",")                    .append(fieldValue).append("]").append(" ");                } else {                    queryBuilder.append(ATTHERATE).append(fieldName).append(":").append(fieldValue).append(" ");                }            }        }        return queryBuilder.toString();    }    private static synchronized void buildOperatorsQuery(StringBuilder buildQuery, String operator, String fieldName, Object fieldValue, Object originFieldValue) {        if (GREATER_THEN.equalsIgnoreCase(operator)) {            buildQuery.append(ATTHERATE).append(fieldName).append(":[")                    .append(getIncrementalVal(originFieldValue)).append(" > ").append(Integer.MAX_VALUE)                    .append("]").append(" ");        } else if (LESS_THEN.equalsIgnoreCase(operator)) {            buildQuery.append(ATTHERATE).append(fieldName).append(":[").append(Integer.MIN_VALUE)                    .append(" < ").append(getDecrementalVal(originFieldValue)).append("]").append(" ");        } else if (GREATER_THEN_EQUAL.equalsIgnoreCase(operator)) {            buildQuery.append(ATTHERATE).append(fieldName).append(":[").append(fieldValue).append(" > ")                    .append(Integer.MAX_VALUE).append("]").append(" ");        } else if (LESS_THEN_EQUAL.equalsIgnoreCase(operator)) {            buildQuery.append(ATTHERATE).append(fieldName).append(":[").append(Integer.MIN_VALUE)                    .append(" < ").append(toValue(fieldValue)).append("]").append(" ");        } else if (BETWEEN.equalsIgnoreCase(operator) && originFieldValue instanceof List) {            List<?> range = (List<?>) originFieldValue;            if (range.size() == 2) {                buildQuery.append(ATTHERATE).append(fieldName).append(":[").append(toValue(range.get(0))).append(",")                        .append(toValue(range.get(1))).append("]").append(" ");            } else {                throw new IllegalArgumentException("Invalid range for 'between' operator");            }        } else {            buildQuery.append(ATTHERATE).append(fieldName).append(":").append(fieldValue).append(" ");        }    }    private static String getKey(String key) {        return key.replace("-", "").replace("_", "");    }    public static <T> T convertDocumentToModel(Document document, Class<T> model) {        Gson gson = new Gson();        String jsonDoc = document.getProperties().iterator().next().getValue().toString();        return gson.fromJson(jsonDoc, model);    }    public static List<String> getNumberFields(Class<?> obj) {        List<String> fieldList = new ArrayList<>();        try {            Class<?> clazz = obj.newInstance().getClass();            Field[] fields = clazz.getDeclaredFields();            for (Field field : fields) {                if (isNumberType(field.getType())) {                    field.setAccessible(true); // Make the field accessible                    fieldList.add(field.getName().toUpperCase());                }            }        } catch (InstantiationException | IllegalAccessException e) {            logger.error("Error while find number fields. {}", e);        }        return fieldList;    }    private static boolean isNumberType(Class<?> fieldType) {        return fieldType == int.class || fieldType == Integer.class || fieldType == long.class                || fieldType == Long.class || fieldType == short.class || fieldType == Short.class                || fieldType == byte.class || fieldType == Byte.class;    }    public static Object toValue(Object value) {        try {            if(value instanceof Date) {                Date date = (Date) value;                return date.getTime();            } else if(value instanceof String) {                return value.toString().trim().replace("-", "*").replace("_", "*");            }        } catch (Exception e) {            logger.error("Error in toValue while parsing value. {}", e);        }        return value;    }    public static Object getIncrementalVal(Object value) {        try {            if(value instanceof Integer || value instanceof Long || value instanceof String) {                long val = Long.parseLong((String) value.toString());                return val + 1;            } else if(value instanceof Double || value instanceof Float) {                double val = Double.parseDouble((String) value.toString());                return val + 0.1;            } else if(value instanceof Date) {                Date date = (Date) value;                Calendar calendar = Calendar.getInstance();                calendar.setTime(date);                // Add one day                calendar.add(Calendar.DAY_OF_YEAR, 1);                return calendar.getTime().getTime();            }        } catch (Exception e) {            logger.error("Error in getIncrementalVal while parsing value. {}", e);        }        return value;    }    public static Object getDecrementalVal(Object value) {        try {            if(value instanceof Integer || value instanceof Long || value instanceof String) {                long val = Long.parseLong((String) value.toString());                return val - 1;            } else if(value instanceof Double || value instanceof Float) {                double val = Double.parseDouble((String) value.toString());                return val - 0.1;            } else if(value instanceof Date) {                Date date = (Date) value;                Calendar calendar = Calendar.getInstance();                calendar.setTime(date);                // Subtract one day                calendar.add(Calendar.DAY_OF_YEAR, -1);                return calendar.getTime().getTime();            }        } catch (Exception e) {            logger.error("Error in getDecrementalVal while parsing value. {}", e);        }        return value;    }}

Save below data by calling BookDataHelper.save method.

bookId = "HFDP-1"title = "Head First Design Patterns"price = 200

Retrieve data by calling BookDataHelper.findByKey method.

BookDataHelper.findByKey("bookdata-idx", "bookId", "HFDP-1", BookData.class);

Unfortunately getting no data result, Also tried with CLI by below command.

FT.SEARCH bookdata-idx @BOOKID:HFDP*1

Viewing all articles
Browse latest Browse all 2203

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>