2014-05-06 15 views
7

Używam dc.js do renderowania ładnego wykresu bąbelkowego zestawu danych. Undercision dc.js to crossfilter.Wymień dane filtru krzyżowego, przywróć wymiary i grupy.

Chciałbym płynnie odświeżyć moją kartę z nowymi danymi z serwera. This issue on Github jasno wynika, że ​​możliwe jest, aby zrobić to poprzez:

  1. usunięcie wszystkich danych z crossfilter
  2. dodając w nowych danych
  3. zawijających dc.redrawAll().

Mam to działa, ale aby usunąć wszystkie dane, musisz najpierw wyczyścić wszystkie filtry (ponieważ crossfilter.remove usuwa jedynie rekordy pasujące do bieżącego filtra).

Chciałbym "zapamiętać", jak moje dane były filtrowane wcześniej, więc mogę zrekonstruować filtr ponownie po wymianie wszystkich danych. Jestem gotów dostać się do odwagi kodu crossfilter, ale pomocne będą wszelkie wskazówki.

Dodatkowo: jeśli ktoś zna sposób aktualizacji danych filtra krzyżowego na podstawie unikalnego klucza, to byłby to złoty pył!

+1

Czy dodajesz tylko dane? Wtedy użyłbym crossfilter.add ([data]). Jeśli chcesz usunąć również dane, nie mam wiele do zaoferowania, ale możesz rzucić okiem na ten problem i skomentować, jeśli brzmi to jak właściwy kierunek: https://github.com/square/crossfilter/issues/109 –

+0

@EthanJewitt Nie dodajemy * ani * usuwania danych. Aktualizuję istniejące dane, każdy wiersz jest unikalnie kluczowany. Czy też "dodaj" ma możliwość aktualizacji na podstawie klucza? – LondonRob

+0

Gotcha - musisz usunąć stare dane i dodać nowe dane (brak możliwości aktualizacji istniejących kluczy, o ile wiem). Ta możliwość w rzeczywistości nie istnieje, ponieważ będziesz musiał usunąć wszystkie filtry, aby usunąć swoje dane. Osobiście uważam, że jest to coś, na co należy się zająć w Crossfilter, i jest dyskusja na ten temat, jak rozwiązać ten problem, ale nie sądzę, by ktokolwiek miał czas na rozwiązanie tego problemu. –

Odpowiedz

1

Dzięki użytkownika @ londonrob Odpowiedź wszystkie dane są teraz usuwane z indeksu. Oto bardziej funkcjonalne podejście do resetowania danych.

// reset the filter for a dimension 
function resetDimensionFilter (dimension) { 
    dimension.filter(null); 
} 

// reset filters for all given dimensions, 
// remove all data from index and 
// return empty index 
function resetData(ndx, dimensions) { 
    // Clear all filters from dimensions, because `ndx.remove` 
    // only removes records matching the current filters. 
    dimensions.forEach(resetDimensionFilter); 

    // Remove all data from the cross filter 
    ndx.remove(); 
} 
+0

Wow! To wspaniała wiadomość. Czy możesz utworzyć link do Github fix/issue/PR, który rozwiązuje ten problem? – LondonRob

+0

Nie jestem pewien, co masz na myśli. Po prostu przepisałem trochę kod, aby wykonać resetowanie. –

+0

Oh. Co więc oznacza "dzięki londonrob'owej odpowiedzi wszystkie dane są teraz usuwane z indeksu"? Jestem zdezorientowany ... – LondonRob

3

Oto, co skończyło się hackowanie razem. To działa doskonale, choć jestem pewien, że to śmiesznie nieefektywne, ponieważ wszystkie wymiary muszą być tworzone od podstaw:

var _xfilter = crossfilter({x:1, y:2},{x:3, y:4}), 
    _dimensions = []; 

_dimensions.push(_xfilter.dimension(function(d) { return d.x; }); 

// Unfilters all the given dimensions, removes all data 
// from xf and adds newData to xf. 
var _xfilter_reset = function(xf, dimensions, newData) { 
    var i; 
    for (i = 0; i < dimensions.length; i++) { 
     // Clear all filters from this dimension. 
     // Necessary because xf.remove only removes records 
     // matching the current filter. 
     dimensions[i].filter(null); 
    } 
    xf.remove(); // Remove all data from the crossfilter 
    xf.add(newData); 
    return xf; 
} 

// Resets the global crossfilter object and reapplies all 
// current dc.js chart filters. 
var _refresh_data = function(data) { 
    var i, j, 
     chart, oldFilters, 
     allCharts = dc.chartRegistry.list(); 

    _xfilter = _xfilter_reset(_xfilter, _dimensions, data);  

    // Reset all filters using dc.js 
    for (i = 0; i < allCharts.length; i++) { 
     chart = allCharts[i]; 
     oldFilters = chart.filters(); // Get current filters 
     chart.filter(null); // Reset all filters on current chart 
     for (j = 0; j < oldFilters.length; j++) { 
      // Set all the oldFilters back onto the chart 
      chart.filter(oldFilters[j]); 
     } 
    } 
    dc.redrawAll(); 
} 
+1

Myślę, że to może być optymalnie skuteczne z tym, co mamy teraz - wszystkie grupy i redukcje muszą zostać ponownie obliczone. Możesz spróbować przebudować filtry, gdy nie ma żadnych danych, więc filtr crossowy nie tasuje indeksów i redukcji dla każdego wywołania '.filter'. Lub możemy mieć nadzieję na wspomnianą wyżej funkcję @Ethan. – Gordon