2016-03-17 21 views
7

Wyobraź sobie, że mam indeksu razy zawierający dokumenty typu „wizyta”, które wyglądają jak następuje:W jaki sposób mogę przekształcić moje dane przed przekształceniem go w histogram?

{ 
       "id": "c223a991-b4e7-4333-ba45-a576010b568b", 
// other properties 
       "buildingId": "48da1a81-fa73-4d4f-aa22-a5750162ed1e", 
       "arrivalDateTimeUtc": "2015-12-22T21:15:00Z" 
} 

Poniższa funkcja zwróci histogram która zwraca wiadra wizyt dla każdego dnia w danym zakresie, zgodnie do podanej strefy czasowej.

public Bucket<HistogramItem> Execute(MyParameterType parameters) 
    { 
     var buildingFilter = Filter<VisitProjection>.Term(x => x.BuildingId, parameters.BuildingId); 
     var dateFilter = Filter<VisitProjection>.Range(r => r 
      .OnField(p => p.ArrivalDateTimeUtc) 
      .GreaterOrEquals(parameters.EarliestArrivalDateTimeUtc) 
      .LowerOrEquals(parameters.LatestArrivalDateTimeUtc) 
     ); 

     var result = _elasticClient.Search<VisitProjection>(s => s 
      .Index("visits") 
      .Type("visit") 
      .Aggregations(a => a 
       .Filter("my_filter_agg", f => f 
        .Filter(fd => buildingFilter && dateFilter) 
         .Aggregations(ta => ta.DateHistogram("my_date_histogram", h => h 
          .Field(p => p.ArrivalDateTimeUtc) 
          .Interval(parameters.DateInterval) // "day" 
          .TimeZone(NodaTimeHelpers.WindowsToIana(parameters.TimeZoneInfo)) // This is a critical piece of the equation. 
          .MinimumDocumentCount(0) 
         ) 
        ) 
       ) 
      ) 
     ); 

     return result.Aggs.Nested("my_filter_agg").DateHistogram("my_date_histogram"); 
    } 
} 

// Returns [{Date: 12/22/2015 12:00:00 AM, DocCount: 1}] 

Teraz wyobraź sobie, że zmienił rzeczy się trochę. Wyobraźmy sobie, że dodałem nowe pole do dokumentu:

{ 
       "id": "c223a991-b4e7-4333-ba45-a576010b568b", 
// other properties 
       "buildingId": "48da1a81-fa73-4d4f-aa22-a5750162ed1e", 
       "arrivalDateTimeUtc": "2015-12-22T21:15:00Z", 
       "departureDateTimeUtc": "2015-12-23T22:00:00Z" // new property 
} 

i zakładamy, że chcę wrócić następujące:

// Returns [{Date: 12/22/2015 12:00:00 AM, DocCount: 1}, {Date: 12/23/2015 12:00:00 AM, DocCount: 1}] 

ponieważ wizyta trwała dwa dni i chcę datę histogram, który rejestruje jeden jednostka na każdy dzień, w którym wizyta obejmuje.

Jak to zrobić w przypadku NEST/Elastic Search?


Uwaga 1: Jeśli ktoś mnie przekona inaczej, nie sądzę, że to dobry pomysł, aby zebrać wszystkie dokumenty w zakresie i przeprowadzenia agregacji/bucketization oraz daty histogram w warstwie pośredniej (lub C# warstwa).

Uwaga 2: Aspekt strefy czasowej tego problemu jest krytyczny, ponieważ potrzebuję zliczeń, które mają zostać podzielone na wiadukty zgodnie z daną strefą czasową.

Odpowiedz

4

Jednym ze sposobów może być użycie scripted_metric aggregation i samodzielne wykonanie samozatapiania na podstawie dwóch pól daty. Bardzo zawiłe i niezbyt wydajne w zależności od tego, ile masz dokumentów.

Jednak inny łatwiej rozwiązaniem może być użycie jednego pole daty i umieścić wszystkie termin przedziału do tablicy (pierwszy przyjazd, odjazd ostatniego i wszelkie inne daty pomiędzy nimi), jak poniżej:

{ 
    "id": "c223a991-b4e7-4333-ba45-a576010b568b", 
    "buildingId": "48da1a81-fa73-4d4f-aa22-a5750162ed1e", 
    "visitDateTimeUtc": ["2015-12-22T21:15:00Z", "2015-12-23T22:00:00Z" ] 
} 

a jeśli wizyta obejmuje trzy/cztery/etc dni, można po prostu „wypełnić” tablicę z czasów między przyjazdu i wyjazdu

{ 
    "id": "c223a991-b4e7-4333-ba45-a576010b568b", 
    "buildingId": "48da1a81-fa73-4d4f-aa22-a5750162ed1e", 
    "visitDateTimeUtc": ["2015-12-22T21:15:00Z", "2015-12-23T22:00:00Z", "2015-12-24T22:00:00Z", "2015-12-25T22:00:00Z" ] 
} 

Dzięki temu wszystkie termin przedziału będą brane pod uwagę przez Twoja agregacja date_histogram.

1

uważam rozwiązania tego problemu poprzez nową właściwość tablicy modelu ES dla VisitDays, więc jeśli ktoś przebywał od 01-Jan-2015 do 05-sty-2015, a następnie model będzie coś takiego:

{ 
    "id" : "c223a991-b4e7-4333-ba45-a576010b568b", 
    // other properties 
    "buildingId" : "48da1a81-fa73-4d4f-aa22-a5750162ed1e", 
    "arrivalDateTimeUtc" : "2015-01-01T21:15:00Z", 
    "departureDateTimeUtc" : "2015-01-05T22:00:00Z", // new property 
    "visitDays" : [ 
     "2015-01-01", 
     "2015-01-02", 
     "2015-01-03", 
     "2015-01-04", 
     "2015-01-05" 
    ] 
} 

Jeśli to zrobiłeś, twoje spinki byłyby bardzo łatwe i bardzo szybkie. Pole skryptowe nie byłoby szybkie. I masz 100% racji, że próba zrobienia tego w C# nie zadziałałaby, ponieważ byłaby zbyt powolna.