github.com/altipla-consulting/ravendb-go-client@v0.1.3/tests/spatial_sorting_test.go (about)

     1  package tests
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	ravendb "github.com/altipla-consulting/ravendb-go-client"
     8  	"github.com/stretchr/testify/assert"
     9  )
    10  
    11  const (
    12  	FilteredLat    = float64(44.419575)
    13  	FilteredLng    = float64(34.042618)
    14  	SortedLat      = float64(44.417398)
    15  	SortedLng      = float64(34.042575)
    16  	FilteredRadius = float64(100)
    17  )
    18  
    19  type Shop struct {
    20  	ID        string
    21  	Latitude  float64 `json:"latitude"`
    22  	Longitude float64 `json:"longitude"`
    23  }
    24  
    25  func NewShop(latitude float64, longitude float64) *Shop {
    26  	return &Shop{
    27  		Latitude:  latitude,
    28  		Longitude: longitude,
    29  	}
    30  }
    31  
    32  var (
    33  	shops = []*Shop{
    34  		NewShop(44.420678, 34.042490),
    35  		NewShop(44.419712, 34.042232),
    36  		NewShop(44.418686, 34.043219),
    37  	}
    38  	//shop/1:0.36KM, shop/2:0.26KM, shop/3 0.15KM from (34.042575,  44.417398)
    39  	sortedExpectedOrder = []string{"shops/3-A", "shops/2-A", "shops/1-A"}
    40  
    41  	//shop/1:0.12KM, shop/2:0.03KM, shop/3 0.11KM from (34.042618,  44.419575)
    42  	filteredExpectedOrder = []string{"shops/2-A", "shops/3-A", "shops/1-A"}
    43  )
    44  
    45  func spatialSortingCreateData(t *testing.T, driver *RavenTestDriver, store *ravendb.DocumentStore) {
    46  	var err error
    47  	indexDefinition := ravendb.NewIndexDefinition()
    48  	indexDefinition.Name = "eventsByLatLng"
    49  	indexDefinition.Maps = []string{"from e in docs.Shops select new { e.venue, coordinates = CreateSpatialField(e.latitude, e.longitude) }"}
    50  
    51  	fields := make(map[string]*ravendb.IndexFieldOptions)
    52  	options := ravendb.NewIndexFieldOptions()
    53  	options.Indexing = ravendb.FieldIndexingExact
    54  	fields["tag"] = options
    55  	indexDefinition.Fields = fields
    56  
    57  	op := ravendb.NewPutIndexesOperation(indexDefinition)
    58  	err = store.Maintenance().Send(op)
    59  	assert.NoError(t, err)
    60  
    61  	indexDefinition2 := ravendb.NewIndexDefinition()
    62  	indexDefinition2.Name = "eventsByLatLngWSpecialField"
    63  	indexDefinition2.Maps = []string{"from e in docs.Shops select new { e.venue, mySpacialField = CreateSpatialField(e.latitude, e.longitude) }"}
    64  
    65  	indexFieldOptions := ravendb.NewIndexFieldOptions()
    66  	indexFieldOptions.Indexing = ravendb.FieldIndexingExact
    67  	fields = map[string]*ravendb.IndexFieldOptions{
    68  		"tag": indexFieldOptions,
    69  	}
    70  	indexDefinition2.Fields = fields
    71  
    72  	op = ravendb.NewPutIndexesOperation(indexDefinition2)
    73  	err = store.Maintenance().Send(op)
    74  	assert.NoError(t, err)
    75  
    76  	{
    77  		session := openSessionMust(t, store)
    78  		for _, shop := range shops {
    79  			err = session.Store(shop)
    80  			assert.NoError(t, err)
    81  		}
    82  
    83  		err = session.SaveChanges()
    84  		assert.NoError(t, err)
    85  
    86  		session.Close()
    87  	}
    88  
    89  	err = driver.waitForIndexing(store, "", 0)
    90  	assert.NoError(t, err)
    91  }
    92  
    93  func assertResultsOrder(t *testing.T, resultIDs []string, expectedOrder []string) {
    94  	ok := stringArrayContainsExactly(resultIDs, expectedOrder)
    95  	assert.True(t, ok)
    96  }
    97  
    98  func spatialSortingCanFilterByLocationAndSortByDistanceFromDifferentPointWDocQuery(t *testing.T,
    99  	driver *RavenTestDriver) {
   100  	store := driver.getDocumentStoreMust(t)
   101  	defer store.Close()
   102  
   103  	spatialSortingCreateData(t, driver, store)
   104  
   105  	{
   106  		session := openSessionMust(t, store)
   107  
   108  		var shops []*Shop
   109  		q := session.QueryIndex("eventsByLatLng")
   110  		fn := func(f *ravendb.SpatialCriteriaFactory) ravendb.SpatialCriteria {
   111  			res := f.Within(getQueryShapeFromLatLon(FilteredLat, FilteredLng, FilteredRadius))
   112  			return res
   113  		}
   114  
   115  		q = q.Spatial3("coordinates", fn)
   116  		q = q.OrderByDistanceLatLong("coordinates", SortedLat, SortedLng)
   117  		err := q.GetResults(&shops)
   118  		assert.NoError(t, err)
   119  		assert.Equal(t, len(shops), len(sortedExpectedOrder))
   120  
   121  		ids := getShopIDs(shops)
   122  		assertResultsOrder(t, ids, sortedExpectedOrder)
   123  
   124  		session.Close()
   125  	}
   126  }
   127  
   128  func getShopIDs(shops []*Shop) []string {
   129  	var res []string
   130  	for _, shop := range shops {
   131  		id := shop.ID
   132  		res = append(res, id)
   133  	}
   134  	return res
   135  }
   136  
   137  func spatialSortingCanSortByDistanceWOFilteringWDocQuery(t *testing.T, driver *RavenTestDriver) {
   138  	store := driver.getDocumentStoreMust(t)
   139  	defer store.Close()
   140  
   141  	spatialSortingCreateData(t, driver, store)
   142  
   143  	{
   144  		session := openSessionMust(t, store)
   145  
   146  		var shops []*Shop
   147  		q := session.QueryIndex("eventsByLatLng")
   148  		q = q.OrderByDistanceLatLong("coordinates", SortedLat, SortedLng)
   149  
   150  		err := q.GetResults(&shops)
   151  		assert.NoError(t, err)
   152  		assert.Equal(t, len(shops), len(sortedExpectedOrder))
   153  
   154  		ids := getShopIDs(shops)
   155  		assertResultsOrder(t, ids, sortedExpectedOrder)
   156  
   157  		session.Close()
   158  	}
   159  }
   160  
   161  func spatialSortingCanSortByDistanceWOFilteringWDocQueryBySpecifiedField(t *testing.T, driver *RavenTestDriver) {
   162  	store := driver.getDocumentStoreMust(t)
   163  	defer store.Close()
   164  
   165  	spatialSortingCreateData(t, driver, store)
   166  
   167  	{
   168  		session := openSessionMust(t, store)
   169  
   170  		var shops []*Shop
   171  		q := session.QueryIndex("eventsByLatLngWSpecialField")
   172  		q = q.OrderByDistanceLatLong("mySpacialField", SortedLat, SortedLng)
   173  		err := q.GetResults(&shops)
   174  		assert.NoError(t, err)
   175  		assert.Equal(t, len(shops), len(sortedExpectedOrder))
   176  
   177  		ids := getShopIDs(shops)
   178  		assertResultsOrder(t, ids, sortedExpectedOrder)
   179  
   180  		session.Close()
   181  	}
   182  }
   183  
   184  func spatialSortingCanSortByDistanceWOFiltering(t *testing.T, driver *RavenTestDriver) {
   185  	store := driver.getDocumentStoreMust(t)
   186  	defer store.Close()
   187  
   188  	spatialSortingCreateData(t, driver, store)
   189  
   190  	{
   191  		session := openSessionMust(t, store)
   192  
   193  		var shops []*Shop
   194  		q := session.QueryIndex("eventsByLatLng")
   195  		q = q.OrderByDistanceLatLong("coordinates", FilteredLat, FilteredLng)
   196  		err := q.GetResults(&shops)
   197  
   198  		assert.NoError(t, err)
   199  		assert.Equal(t, len(shops), len(filteredExpectedOrder))
   200  
   201  		ids := getShopIDs(shops)
   202  		assertResultsOrder(t, ids, filteredExpectedOrder)
   203  
   204  		session.Close()
   205  	}
   206  
   207  	{
   208  		session := openSessionMust(t, store)
   209  
   210  		var shops []*Shop
   211  		q := session.QueryIndex("eventsByLatLng")
   212  		q = q.OrderByDistanceDescendingLatLong("coordinates", FilteredLat, FilteredLng)
   213  		err := q.GetResults(&shops)
   214  
   215  		assert.NoError(t, err)
   216  		assert.Equal(t, len(shops), len(filteredExpectedOrder))
   217  
   218  		ids := getShopIDs(shops)
   219  		stringArrayReverse(ids)
   220  		assertResultsOrder(t, ids, filteredExpectedOrder)
   221  
   222  		session.Close()
   223  	}
   224  }
   225  
   226  func spatialSortingCanSortByDistanceWOFilteringBySpecifiedField(t *testing.T, driver *RavenTestDriver) {
   227  	store := driver.getDocumentStoreMust(t)
   228  	defer store.Close()
   229  
   230  	spatialSortingCreateData(t, driver, store)
   231  
   232  	{
   233  		session := openSessionMust(t, store)
   234  
   235  		var shops []*Shop
   236  		q := session.QueryIndex("eventsByLatLngWSpecialField")
   237  		q = q.OrderByDistanceLatLong("mySpacialField", FilteredLat, FilteredLng)
   238  		err := q.GetResults(&shops)
   239  
   240  		assert.NoError(t, err)
   241  		assert.Equal(t, len(shops), len(filteredExpectedOrder))
   242  
   243  		ids := getShopIDs(shops)
   244  		assertResultsOrder(t, ids, filteredExpectedOrder)
   245  
   246  		session.Close()
   247  	}
   248  
   249  	{
   250  		session := openSessionMust(t, store)
   251  
   252  		var shops []*Shop
   253  		q := session.QueryIndex("eventsByLatLngWSpecialField")
   254  		q = q.OrderByDistanceDescendingLatLong("mySpacialField", FilteredLat, FilteredLng)
   255  		err := q.GetResults(&shops)
   256  
   257  		assert.NoError(t, err)
   258  		assert.Equal(t, len(shops), len(filteredExpectedOrder))
   259  
   260  		ids := getShopIDs(shops)
   261  		stringArrayReverse(ids)
   262  		assertResultsOrder(t, ids, filteredExpectedOrder)
   263  
   264  		session.Close()
   265  	}
   266  }
   267  
   268  func getQueryShapeFromLatLon(lat float64, lng float64, radius float64) string {
   269  	return fmt.Sprintf("Circle(%f %f d=%f)", lng, lat, radius)
   270  }
   271  
   272  func TestSpatialSorting(t *testing.T) {
   273  	driver := createTestDriver(t)
   274  	destroy := func() { destroyDriver(t, driver) }
   275  	defer recoverTest(t, destroy)
   276  
   277  	// matches order of Java tests
   278  	spatialSortingCanSortByDistanceWOFilteringBySpecifiedField(t, driver)
   279  	spatialSortingCanFilterByLocationAndSortByDistanceFromDifferentPointWDocQuery(t, driver)
   280  	spatialSortingCanSortByDistanceWOFiltering(t, driver)
   281  	spatialSortingCanSortByDistanceWOFilteringWDocQuery(t, driver)
   282  	spatialSortingCanSortByDistanceWOFilteringWDocQueryBySpecifiedField(t, driver)
   283  }