Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions Examples/GeoShape.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# GeoShape Fields Usage In RediSearch

As of RediSearch 2.8.4, advanced GEO querying with GEOSHAPE fields is supported.

Any object/library producing a
[well-known text (WKT)](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry) in `string` format can be used.

In this example, we'll demonstrate how to use GeoShape fields in RediSearch with [NetTopologySuite](https://github.com/NetTopologySuite/NetTopologySuite) library.

## Example

### Modules Needed

```c#
using StackExchange.Redis;
using NRedisStack.RedisStackCommands;
using NRedisStack.Search;
using NetTopologySuite.Geometries;
using NetTopologySuite.IO;
```

### Setup

```csharp
// Connect to the Redis server:
var redis = ConnectionMultiplexer.Connect("localhost");
var db = redis.GetDatabase();
// Get a reference to the database and for search commands:
var ft = db.FT();

// Create WTKReader and GeometryFactory objects:
WKTReader reader = new WKTReader();
GeometryFactory factory = new GeometryFactory();

```

### Create the index

```csharp
ft.Create(index, new Schema().AddGeoShapeField("geom", GeoShapeField.CoordinateSystem.FLAT));
```

### Prepare the data

```csharp
Polygon small = factory.CreatePolygon(new Coordinate[]{new Coordinate(1, 1),
new Coordinate(1, 100), new Coordinate(100, 100), new Coordinate(100, 1), new Coordinate(1, 1)});
db.HashSet("small", "geom", small.ToString());

Polygon large = factory.CreatePolygon(new Coordinate[]{new Coordinate(1, 1),
new Coordinate(1, 200), new Coordinate(200, 200), new Coordinate(200, 1), new Coordinate(1, 1)});
db.HashSet("large", "geom", large.ToString());
```

## Polygon type

### Querying within condition

```csharp
Polygon within = factory.CreatePolygon(new Coordinate[]{new Coordinate(0, 0),
new Coordinate(0, 150), new Coordinate(150, 150), new Coordinate(150, 0), new Coordinate(0, 0)});

SearchResult res = ft.Search(index, new Query("@geom:[within $poly]").AddParam("poly", within.ToString()).Dialect(3));
```

The search result from redis is:

```bash
1) (integer) 1
2) "small"
3) 1) "geom"
2) "POLYGON ((1 1, 1 100, 100 100, 100 1, 1 1))"
```

we can use the reader to get the polygon object:

```csharp
reader.Read(res.Documents[0]["geom"].ToString());
```

### Querying contains condition

```csharp
Polygon contains = factory.CreatePolygon(new Coordinate[]{new Coordinate(2, 2),
new Coordinate(2, 50), new Coordinate(50, 50), new Coordinate(50, 2), new Coordinate(2, 2)});

res = ft.Search(index, new Query("@geom:[contains $poly]").AddParam("poly", contains.ToString()).Dialect(3)); // DIALECT 3 is required for this query

```

The search result from redis is:

```bash
1) (integer) 2
2) "small"
3) 1) "geom"
2) "POLYGON ((1 1, 1 100, 100 100, 100 1, 1 1))"
4) "large"
5) 1) "geom"
2) "POLYGON ((1 1, 1 200, 200 200, 200 1, 1 1))"
```

### Point type
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Searching with Co-ordinates


```csharp
Point point = factory.CreatePoint(new Coordinate(10, 10));
db.HashSet("point", "geom", point.ToString());

res = ft.Search(index, new Query("@geom:[within $poly]").AddParam("poly", within.ToString()).Dialect(3));

```

The search result from redis is:

```bash
1) (integer) 2
2) "small"
3) 1) "geom"
2) "POLYGON ((1 1, 1 100, 100 100, 100 1, 1 1))"
4) "point"
5) 1) "geom"
2) "POINT (10 10)"
```
3 changes: 2 additions & 1 deletion src/NRedisStack/NRedisStack.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="NetTopologySuite" Version="2.5.0" />
<PackageReference Include="System.Text.Json" Version="7.0.2" Condition="'$(TargetFramework)' == 'netstandard2.0'" />
<PackageReference Include="StackExchange.Redis" Version="2.6.96" />
<PackageReference Include="StackExchange.Redis" Version="2.6.122" />
<None Include="..\..\README.md" Pack="true" PackagePath="\" />
</ItemGroup>

Expand Down
1 change: 1 addition & 0 deletions src/NRedisStack/Search/Query.cs
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,7 @@ public Query SetSortBy(string field, bool? ascending = null)
/// Parameters can be referenced in the query string by a $ , followed by the parameter name,
/// e.g., $user , and each such reference in the search query to a parameter name is substituted
/// by the corresponding parameter value.
/// Note: when calling this function with an externally supplied parameter, value should be a string.
/// </summary>
/// <param name="name"></param>
/// <param name="value"> can be String, long or float</param>
Expand Down
58 changes: 58 additions & 0 deletions src/NRedisStack/Search/Schema.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NRedisStack.Search.Literals;
using static NRedisStack.Search.Schema.GeoShapeField;
using static NRedisStack.Search.Schema.VectorField;

namespace NRedisStack.Search
Expand All @@ -13,6 +14,7 @@ public enum FieldType
{
Text,
Geo,
GeoShape,
Numeric,
Tag,
Vector
Expand All @@ -38,6 +40,7 @@ internal void AddSchemaArgs(List<object> args)
{
FieldType.Text => "TEXT",
FieldType.Geo => "GEO",
FieldType.GeoShape => "GEOSHAPE",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good

FieldType.Numeric => "NUMERIC",
FieldType.Tag => "TAG",
FieldType.Vector => "VECTOR",
Expand Down Expand Up @@ -178,6 +181,37 @@ internal override void AddFieldTypeArgs(List<object> args)

}

public class GeoShapeField : Field
{
public enum CoordinateSystem
{
/// <summary>
/// For cartesian (X,Y).
/// </summary>
FLAT,

/// <summary>
/// For geographic (lon, lat).
/// </summary>
SPHERICAL
}
private CoordinateSystem system { get; }

internal GeoShapeField(FieldName name, CoordinateSystem system)
: base(name, FieldType.GeoShape)
{
this.system = system;
}

internal GeoShapeField(string name, CoordinateSystem system)
: this(FieldName.Of(name), system) { }

internal override void AddFieldTypeArgs(List<object> args)
{
args.Add(system.ToString());
}
}

public class NumericField : Field
{
public bool Sortable { get; }
Expand Down Expand Up @@ -288,6 +322,30 @@ public Schema AddTextField(FieldName name, double weight = 1.0, bool sortable =
return this;
}

/// <summary>
/// Add a GeoShape field to the schema.
/// </summary>
/// <param name="name">The field's name.</param>
/// <param name="system">The coordinate system to use.</param>
/// <returns>The <see cref="Schema"/> object.</returns>
public Schema AddGeoShapeField(string name, CoordinateSystem system)
{
Fields.Add(new GeoShapeField(name, system));
return this;
}

/// <summary>
/// Add a GeoShape field to the schema.
/// </summary>
/// <param name="name">The field's name.</param>
/// <param name="system">The coordinate system to use.</param>
/// <returns>The <see cref="Schema"/> object.</returns>
public Schema AddGeoShapeField(FieldName name, CoordinateSystem system)
{
Fields.Add(new GeoShapeField(name, system));
return this;
}

/// <summary>
/// Add a Geo field to the schema.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion tests/Doc/Doc.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="StackExchange.Redis" Version="2.6.104" />
<PackageReference Include="StackExchange.Redis" Version="2.6.122" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\NRedisStack\NRedisStack.csproj" />
Expand Down
2 changes: 2 additions & 0 deletions tests/NRedisStack.Tests/Examples/ExampleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1373,6 +1373,8 @@ public void AdvancedQueryOperationsTest()
Assert.Equal(expectedResSet, resSet);
}

// GeoShape Example Test is in SearchTests.cs, The test name is: GeoShapeFilterFlat.

private static void SortAndCompare(List<string> expectedList, List<string> res)
{
res.Sort();
Expand Down
5 changes: 3 additions & 2 deletions tests/NRedisStack.Tests/NRedisStack.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@
</PackageReference>
<PackageReference Include="dotenv.net" Version="3.1.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="NetTopologySuite" Version="2.5.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
<PackageReference Include="StackExchange.Redis" Version="2.6.96" />
<PackageReference Include="StackExchange.Redis" Version="2.6.122" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.assert" Version="2.4.1" />
<PackageReference Include="BouncyCastle.Cryptography" Version="2.2.0"/>
<PackageReference Include="BouncyCastle.Cryptography" Version="2.2.0" />
</ItemGroup>

<ItemGroup>
Expand Down
Loading