redis / redis-om-spring

Spring Data Redis extensions for better search, documents models, and more
MIT License
590 stars 92 forks source link

SEQUENCE OR QUERY #479

Open SylvainAssemat opened 1 month ago

SylvainAssemat commented 1 month ago

Hi all

Just to expose an experience on a simple query that seems not well executed depending on syntax ?! Maybe could you find or explain why there is a difference ? Thanks for your help (-> delete this ticket if nothing relevant for anyone)

First way : (copy/paste from redis monitor) , generated by the redis om lib 0.9.2 This one is not working : ❌ "Syntax error at offset 967 near ezn"

"FT.SEARCH" "RDGeoMarkerIdx" "(( @mapConfigId:{9e6c022e\\-9f64\\-4bc2\\-9bc5\\-0f5fa98c74a5}) ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( @geohash:{ewz*})|( @geohash:{exp*}))|( @geohash:{exr*}))|( @geohash:{exx*}))|( @geohash:{exz*}))|( @geohash:{eyb*}))|( @geohash:{eyc*}))|( @geohash:{eyf*}))|( @geohash:{eyg*}))|( @geohash:{eyu*}))|( @geohash:{eyv*}))|( @geohash:{eyy*}))|( @geohash:{eyz*}))|( @geohash:{ez0*}))|( @geohash:{ez1*}))|( @geohash:{ez2*}))|( @geohash:{ez3*}))|( @geohash:{ez4*}))|( @geohash:{ez5*}))|( @geohash:{ez6*}))|( @geohash:{ez7*}))|( @geohash:{ez8*}))|( @geohash:{ez9*}))|( @geohash:{ezb*}))|( @geohash:{ezc*}))|( @geohash:{ezd*}))|( @geohash:{eze*}))|( @geohash:{ezf*}))|( @geohash:{ezg*}))|( @geohash:{ezh*}))|( @geohash:{ezj*}))|( @geohash:{ezk*}))|( @geohash:{ezm*}))|( @geohash:{**ezn***}))|( @geohash:{ezp*}))|( @geohash:{ezq*}))|( @geohash:{ezr*}))|( @geohash:{ezs*}))|( @geohash:{ezt*}))|( @geohash:{ezu*}))|( @geohash:{ezv*}))|( @geohash:{ezw*}))|( @geohash:{ezx*}))|( @geohash:{ezy*}))|( @geohash:{ezz*}))|( @geohash:{g8p*}))|( @geohash:{g8r*}))|( @geohash:{g8x*}))|( @geohash:{g8z*}))|( @geohash:{g9p*}))|( @geohash:{g9r*}))|( @geohash:{gb0*}))|( @geohash:{gb1*}))|( @geohash:{gb2*}))|( @geohash:{gb3*}))|( @geohash:{gb4*}))|( @geohash:{gb5*}))|( @geohash:{gb6*}))|( @geohash:{gb7*}))|( @geohash:{gb8*}))|( @geohash:{gb9*}))|( @geohash:{gbb*}))|( @geohash:{gbc*}))|( @geohash:{gbd*}))|( @geohash:{gbe*}))|( @geohash:{gbf*}))|( @geohash:{gbg*}))|( @geohash:{gbh*}))|( @geohash:{gbj*}))|( @geohash:{gbk*}))|( @geohash:{gbm*}))|( @geohash:{gbn*}))|( @geohash:{gbp*}))|( @geohash:{gbq*}))|( @geohash:{gbr*}))|( @geohash:{gbs*}))|( @geohash:{gbt*}))|( @geohash:{gbu*}))|( @geohash:{gbv*}))|( @geohash:{gbw*}))|( @geohash:{gbx*}))|( @geohash:{gby*}))|( @geohash:{gbz*}))|( @geohash:{gc0*}))|( @geohash:{gc1*}))|( @geohash:{gc2*}))|( @geohash:{gc3*}))|( @geohash:{gc4*}))|( @geohash:{gc5*}))|( @geohash:{gc6*}))|( @geohash:{gc7*}))|( @geohash:{gch*}))|( @geohash:{gcj*}))|( @geohash:{gck*}))|( @geohash:{gcm*}))|( @geohash:{gcn*}))|( @geohash:{gcp*}))|( @geohash:{gcq*}))|( @geohash:{gcr*}))|( @geohash:{snb*}))|( @geohash:{snc*}))|( @geohash:{snf*}))|( @geohash:{sng*}))|( @geohash:{snu*}))|( @geohash:{snv*}))|( @geohash:{sny*}))|( @geohash:{snz*}))|( @geohash:{sp0*}))|( @geohash:{sp1*}))|( @geohash:{sp2*}))|( @geohash:{sp3*}))|( @geohash:{sp4*}))|( @geohash:{sp5*}))|( @geohash:{sp6*}))|( @geohash:{sp7*}))|( @geohash:{sp8*}))|( @geohash:{sp9*}))|( @geohash:{spb*}))|( @geohash:{spc*}))|( @geohash:{spd*}))|( @geohash:{spe*}))|( @geohash:{spf*}))|( @geohash:{spg*}))|( @geohash:{sph*}))|( @geohash:{spj*}))|( @geohash:{spk*}))|( @geohash:{spm*}))|( @geohash:{spn*}))|( @geohash:{spp*}))|( @geohash:{spq*}))|( @geohash:{spr*}))|( @geohash:{sps*}))|( @geohash:{spt*}))|( @geohash:{spu*}))|( @geohash:{spv*}))|( @geohash:{spw*}))|( @geohash:{spx*}))|( @geohash:{spy*}))|( @geohash:{spz*}))|( @geohash:{sqb*}))|( @geohash:{sqc*}))|( @geohash:{sqf*}))|( @geohash:{sqg*}))|( @geohash:{sr0*}))|( @geohash:{sr1*}))|( @geohash:{sr2*}))|( @geohash:{sr3*}))|( @geohash:{sr4*}))|( @geohash:{sr5*}))|( @geohash:{sr6*}))|( @geohash:{sr7*}))|( @geohash:{sr8*}))|( @geohash:{sr9*}))|( @geohash:{srb*}))|( @geohash:{src*}))|( @geohash:{srd*}))|( @geohash:{sre*}))|( @geohash:{srf*}))|( @geohash:{srg*}))|( @geohash:{u00*}))|( @geohash:{u01*}))|( @geohash:{u02*}))|( @geohash:{u03*}))|( @geohash:{u04*}))|( @geohash:{u05*}))|( @geohash:{u06*}))|( @geohash:{u07*}))|( @geohash:{u08*}))|( @geohash:{u09*}))|( @geohash:{u0b*}))|( @geohash:{u0c*}))|( @geohash:{u0d*}))|( @geohash:{u0e*}))|( @geohash:{u0f*}))|( @geohash:{u0g*}))|( @geohash:{u0h*}))|( @geohash:{u0j*}))|( @geohash:{u0k*}))|( @geohash:{u0m*}))|( @geohash:{u0n*}))|( @geohash:{u0p*}))|( @geohash:{u0q*}))|( @geohash:{u0r*}))|( @geohash:{u0s*}))|( @geohash:{u0t*}))|( @geohash:{u0u*}))|( @geohash:{u0v*}))|( @geohash:{u0w*}))|( @geohash:{u0x*}))|( @geohash:{u0y*}))|( @geohash:{u0z*}))|( @geohash:{u10*}))|( @geohash:{u11*}))|( @geohash:{u12*}))|( @geohash:{u13*}))|( @geohash:{u14*}))|( @geohash:{u15*}))|( @geohash:{u16*}))|( @geohash:{u17*}))|( @geohash:{u1h*}))|( @geohash:{u1j*}))|( @geohash:{u1k*}))|( @geohash:{u1m*}))|( @geohash:{u1n*}))|( @geohash:{u1p*}))|( @geohash:{u1q*}))|( @geohash:{u1r*}))|( @geohash:{u20*}))|( @geohash:{u21*}))|( @geohash:{u22*}))|( @geohash:{u23*}))|( @geohash:{u24*}))|( @geohash:{u25*}))|( @geohash:{u26*}))|( @geohash:{u27*}))|( @geohash:{u28*}))|( @geohash:{u29*}))|( @geohash:{u2b*}))|( @geohash:{u2c*}))|( @geohash:{u2d*}))|( @geohash:{u2e*}))|( @geohash:{u2f*}))|( @geohash:{u2g*}))|( @geohash:{u30*}))|( @geohash:{u31*}))|( @geohash:{u32*}))|( @geohash:{u33*}))|( @geohash:{u34*}))|( @geohash:{u35*}))|( @geohash:{u36*}))|( @geohash:{u37*})))"

Other way, i clean it to be more readable. This way is working ✅

 "FT.SEARCH" "RDGeoMarkerIdx" "(
 ( @mapConfigId:{9e6c022e\\-9f64\\-4bc2\\-9bc5\\-0f5fa98c74a5}) 
 (
 ( @geohash:{ewz*})|
 ( @geohash:{exp*})|
 ( @geohash:{exr*})|
 ( @geohash:{exx*})|
 ( @geohash:{exz*})|
 ( @geohash:{eyb*})|
 ( @geohash:{eyc*})|
 ( @geohash:{eyf*})|
 ( @geohash:{eyg*})|
 ( @geohash:{eyu*})|
 ( @geohash:{eyv*})|
 ( @geohash:{eyy*})|
 ( @geohash:{eyz*})|
 ( @geohash:{ez0*})|
 ( @geohash:{ez1*})|
 ( @geohash:{ez2*})|
 ( @geohash:{ez3*})|
 ( @geohash:{ez4*})|
 ( @geohash:{ez5*})|
 ( @geohash:{ez6*})|
 ( @geohash:{ez7*})|
 ( @geohash:{ez8*})|
 ( @geohash:{ez9*})|
 ( @geohash:{ezb*})|
 ( @geohash:{ezc*})|
 ( @geohash:{ezd*})|
 ( @geohash:{eze*})|
 ( @geohash:{ezf*})|
 ( @geohash:{ezg*})|
 ( @geohash:{ezh*})|
 ( @geohash:{ezj*})|
 ( @geohash:{ezk*})|
 ( @geohash:{ezm*})|
 ( @geohash:{ezn*})|
 ( @geohash:{ezp*})|
 ( @geohash:{ezq*})|
 ( @geohash:{ezr*})|
 ( @geohash:{ezs*})|
 ( @geohash:{ezt*})|
 ( @geohash:{ezu*})|
 ( @geohash:{ezv*})|
 ( @geohash:{ezw*})|
 ( @geohash:{ezx*})|
 ( @geohash:{ezy*})|
 ( @geohash:{ezz*})|
 ( @geohash:{g8p*})|
 ( @geohash:{g8r*})|
 ( @geohash:{g8x*})|
 ( @geohash:{g8z*})|
 ( @geohash:{g9p*})|
 ( @geohash:{g9r*})|
 ( @geohash:{gb0*})|
 ( @geohash:{gb1*})|
 ( @geohash:{gb2*})|
 ( @geohash:{gb3*})|
 ( @geohash:{gb4*})|
 ( @geohash:{gb5*})|
 ( @geohash:{gb6*})|
 ( @geohash:{gb7*})|
 ( @geohash:{gb8*})|
 ( @geohash:{gb9*})|
 ( @geohash:{gbb*})|
 ( @geohash:{gbc*})|
 ( @geohash:{gbd*})|
 ( @geohash:{gbe*})|
 ( @geohash:{gbf*})|
 ( @geohash:{gbg*})|
 ( @geohash:{gbh*})|
 ( @geohash:{gbj*})|
 ( @geohash:{gbk*})|
 ( @geohash:{gbm*})|
 ( @geohash:{gbn*})|
 ( @geohash:{gbp*})|
 ( @geohash:{gbq*})|
 ( @geohash:{gbr*})|
 ( @geohash:{gbs*})|
 ( @geohash:{gbt*})|
 ( @geohash:{gbu*})|
 ( @geohash:{gbv*})|
 ( @geohash:{gbw*})|
 ( @geohash:{gbx*})|
 ( @geohash:{gby*})|
 ( @geohash:{gbz*})|
 ( @geohash:{gc0*})|
 ( @geohash:{gc1*})|
 ( @geohash:{gc2*})|
 ( @geohash:{gc3*})|
 ( @geohash:{gc4*})|
 ( @geohash:{gc5*})|
 ( @geohash:{gc6*})|
 ( @geohash:{gc7*})|
 ( @geohash:{gch*})|
 ( @geohash:{gcj*})|
 ( @geohash:{gck*})|
 ( @geohash:{gcm*})|
 ( @geohash:{gcn*})|
 ( @geohash:{gcp*})|
 ( @geohash:{gcq*})|
 ( @geohash:{gcr*})|
 ( @geohash:{snb*})|
 ( @geohash:{snc*})|
 ( @geohash:{snf*})|
 ( @geohash:{sng*})|
 ( @geohash:{snu*})|
 ( @geohash:{snv*})|
 ( @geohash:{sny*})|
 ( @geohash:{snz*})|
 ( @geohash:{sp0*})|
 ( @geohash:{sp1*})|
 ( @geohash:{sp2*})|
 ( @geohash:{sp3*})|
 ( @geohash:{sp4*})|
 ( @geohash:{sp5*})|
 ( @geohash:{sp6*})|
 ( @geohash:{sp7*})|
 ( @geohash:{sp8*})|
 ( @geohash:{sp9*})|
 ( @geohash:{spb*})|
 ( @geohash:{spc*})|
 ( @geohash:{spd*})|
 ( @geohash:{spe*})|
 ( @geohash:{spf*})|
 ( @geohash:{spg*})|
 ( @geohash:{sph*})|
 ( @geohash:{spj*})|
 ( @geohash:{spk*})|
 ( @geohash:{spm*})|
 ( @geohash:{spn*})|
 ( @geohash:{spp*})|
 ( @geohash:{spq*})|
 ( @geohash:{spr*})|
 ( @geohash:{sps*})|
 ( @geohash:{spt*})|
 ( @geohash:{spu*})|
 ( @geohash:{spv*})|
 ( @geohash:{spw*})|
 ( @geohash:{spx*})|
 ( @geohash:{spy*})|
 ( @geohash:{spz*})|
 ( @geohash:{sqb*})|
 ( @geohash:{sqc*})|
 ( @geohash:{sqf*})|
 ( @geohash:{sqg*})|
 ( @geohash:{sr0*})|
 ( @geohash:{sr1*})|
 ( @geohash:{sr2*})|
 ( @geohash:{sr3*})|
 ( @geohash:{sr4*})|
 ( @geohash:{sr5*})|
 ( @geohash:{sr6*})|
 ( @geohash:{sr7*})|
 ( @geohash:{sr8*})|
 ( @geohash:{sr9*})|
 ( @geohash:{srb*})|
 ( @geohash:{src*})|
 ( @geohash:{srd*})|
 ( @geohash:{sre*})|
 ( @geohash:{srf*})|
 ( @geohash:{srg*})|
 ( @geohash:{u00*})|
 ( @geohash:{u01*})|
 ( @geohash:{u02*})|
 ( @geohash:{u03*})|
 ( @geohash:{u04*})|
 ( @geohash:{u05*})|
 ( @geohash:{u06*})|
 ( @geohash:{u07*})|
 ( @geohash:{u08*})|
 ( @geohash:{u09*})|
 ( @geohash:{u0b*})|
 ( @geohash:{u0c*})|
 ( @geohash:{u0d*})|
 ( @geohash:{u0e*})|
 ( @geohash:{u0f*})|
 ( @geohash:{u0g*})|
 ( @geohash:{u0h*})|
 ( @geohash:{u0j*})|
 ( @geohash:{u0k*})|
 ( @geohash:{u0m*})|
 ( @geohash:{u0n*})|
 ( @geohash:{u0p*})|
 ( @geohash:{u0q*})|
 ( @geohash:{u0r*})|
 ( @geohash:{u0s*})|
 ( @geohash:{u0t*})|
 ( @geohash:{u0u*})|
 ( @geohash:{u0v*})|
 ( @geohash:{u0w*})|
 ( @geohash:{u0x*})|
 ( @geohash:{u0y*})|
 ( @geohash:{u0z*})|
 ( @geohash:{u10*})|
 ( @geohash:{u11*})|
 ( @geohash:{u12*})|
 ( @geohash:{u13*})|
 ( @geohash:{u14*})|
 ( @geohash:{u15*})|
 ( @geohash:{u16*})|
 ( @geohash:{u17*})|
 ( @geohash:{u1h*})|
 ( @geohash:{u1j*})|
 ( @geohash:{u1k*})|
 ( @geohash:{u1m*})|
 ( @geohash:{u1n*})|
 ( @geohash:{u1p*})|
 ( @geohash:{u1q*})|
 ( @geohash:{u1r*})|
 ( @geohash:{u20*})|
 ( @geohash:{u21*})|
 ( @geohash:{u22*})|
 ( @geohash:{u23*})|
 ( @geohash:{u24*})|
 ( @geohash:{u25*})|
 ( @geohash:{u26*})|
 ( @geohash:{u27*})|
 ( @geohash:{u28*})|
 ( @geohash:{u29*})|
 ( @geohash:{u2b*})|
 ( @geohash:{u2c*})|
 ( @geohash:{u2d*})|
 ( @geohash:{u2e*})|
 ( @geohash:{u2f*})|
 ( @geohash:{u2g*})|
 ( @geohash:{u30*})|
 ( @geohash:{u31*})|
 ( @geohash:{u32*})|
 ( @geohash:{u33*})|
 ( @geohash:{u34*})|
 ( @geohash:{u35*})|
 ( @geohash:{u36*})|
 ( @geohash:{u37*}))
 )"
bsbodden commented 1 month ago

Post you code please, thanks

SylvainAssemat commented 1 month ago

Hello

Here it is :

Predicate orGeohash = searchRequest.getListGeoHash().stream().map(el -> (Predicate) RDGeoMarker$.GEOHASH.startsWith(el)).reduce(Predicate::or).orElse(p -> false);

SearchStream<RDGeoMarker> searchStream = entityStream.of(RDGeoMarker.class);
        searchStream = searchStream.filter(predicate);
        searchStream = searchStream.skip(0);
        searchStream = searchStream.limit(Integer.MAX_VALUE);

image

But seems to work with a manual syntax

List<String> conditions = new ArrayList<>();
String orGeohash = searchRequest.getListGeoHash().stream()
                    .map(el -> el + "*")
                    .collect(Collectors.joining("|"));
            conditions.add("@geohash:{" + orGeohash + "}");

SearchStream<RDGeoMarker> searchStream = entityStream.of(RDGeoMarker.class);
        searchStream = searchStream.filter(conditions.stream().collect(Collectors.joining(" ")));
        searchStream = searchStream.skip(0);
        searchStream = searchStream.limit(Integer.MAX_VALUE);

image

image

bsbodden commented 1 month ago

@SylvainAssemat Can you post the code for the RDGeoMarker class and perhaps some fake testing data?

SylvainAssemat commented 2 weeks ago

Here it is :

package com.globalsaas.mappilot.redis.model;

import java.util.Map;
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.Indexed;
import com.redis.om.spring.annotations.Searchable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;

@Data
@Builder
@RequiredArgsConstructor(staticName = "of")
@AllArgsConstructor
@NoArgsConstructor
@Document
public class RDGeoMarker {
    // Id Field, also indexed

    @Id
    @NonNull
    @Indexed(alias = "UID")
    private String uid;

    @Indexed(alias = "ID")
    @NonNull
    private String geoMarkerId;

    @Indexed
    @NonNull
    private String mapConfigId;

    private String name;
    private String category;
    //private String tooltip;
    private String type;
    private String icon;
    private String color;
    private String charValue;

    @Indexed
    @NonNull
    private Double longitude;

    @Indexed
    @NonNull
    private Double latitude;

    private Long limitCoordStorage;

    @Searchable(alias = "adresse")
    private String address;
    private String style;

    @Indexed
    @NonNull
    private String geohash;
    //private String listItemText;

    // style values
    //private String iconUrl;
    //private String markerPath;
    //private String markerColor;
    //private String infoWindow;
    //private String fontAwesomeColor;
    //private String fontAwesomeText;

    @Indexed(alias = "geoLoc")
    @NonNull
    private Point geoPoint;

    private Map<String, Object> props;
}
bsbodden commented 2 weeks ago

@SylvainAssemat one comment on the above class,@Id automatically makes the field indexed as a TAG, so the extra @Indexed is unnecessary.

Also geohash is indexed as a TAG, so adding * would have no effect on it, TAG (see https://redis.io/docs/latest/develop/interact/search-and-query/advanced-concepts/tags/) fields support exact matches only. To use * you would need to use @Searchable to index it as TEXT (see https://redis.io/docs/latest/develop/interact/search-and-query/query/full-text/)