ElasticSearch 와 Protovis 로 데이터 시각 화

28283 단어 elasticsearch
검색엔진 의 가장 중요 한 목적 은, 응, 의외로 검색 이 야.당신 이 그것 에 게 요청 을 한 후에 그것 은 관련 성에 따라 당신 이 일치 하 는 결 과 를 되 돌려 줍 니 다.우 리 는 자신의 내용 에 따라 각종 요청 구 조 를 만 들 고 다양한 분석 기 를 시험 할 수 있 으 며 검색엔진 은 최선 의 결 과 를 제공 하려 고 노력 할 것 이다.
하지만 현대 전문 검색엔진 은 이것 보다 더 많이 할 수 있다.그 핵심 은 일치 하 는 문 서 를 효율적으로 조회 하기 위해 고도 로 최 적 화 된 데이터 구조 인 역 배열 색인 을 바탕 으로 하기 때문이다.그것 도 우리 의 데 이 터 를 위해 복잡 한 취 합 연산 을 완성 할 수 있 습 니 다. 여기 서 우 리 는 그것 을 facets 라 고 부 릅 니 다.(번역 하기 가 쉽 지 않 습 니 다. 뒷글 은 이 단어 에 대해 모두 영 어 를 보존 합 니 다)
facets 의 일반적인 목적 은 사용자 에 게 어떤 방면 의 내 비게 이 션 이나 검색 을 제공 하 는 것 이다.인터넷 상점 에서 '카메라' 를 검색 하면 서로 다른 제조 업 체, 가격 범위 나 특정한 기능 을 선택 하여 조건 을 정할 수 있다. 이것 은 긴 검색 문법 을 수정 하 는 것 이 아니 라 링크 를 클릭 하 는 것 이다.Facet 검색 은 강력 한 요청 능력 을 최종 사용자 에 게 개방 할 수 있 는 몇 가지 방법 중 하나 입 니 다. Moritz Stefaner 의 테스트 "Elastic Lists" 를 참조 하면 더 많은 영감 을 얻 을 수 있 습 니 다.
하지만 링크 와 체크 상 자 를 제외 하고 우 리 는 더 많이 할 수 있다.예 를 들 어 이런 데 이 터 를 이용 하여 그림 을 그 리 는 것 이 바로 우리 가 이 글 에서 말 하고 자 하 는 것 이다.
실시 간 계기판 은 거의 모든 분석, 감시 와 데이터 발굴 서비스 에서 이 르 거나 늦 은 당신 은 이러한 수 요 를 만 날 수 있 습 니 다. "우 리 는 계기판 을 원 합 니 다!"모두 가 계기판 을 사랑 하기 때문에 정말 유용 하기 때 문 일 수도 있 습 니 다. 단순히 예 쁘 기 때 문 일 수도 있 습 니 다. 이 럴 때 우 리 는 어떠한 OLAP 도 쓰 지 않 고 facets 로 예 쁘 고 기 똥 찬 분석 엔진 을 완성 할 수 있 습 니 다.
아래 의 캡 처 는 소 셜 미디어 모니터링 애플 리 케 이 션 에서 얻 은 것 이다.이 응용 프로그램 은 ES 로 만 데 이 터 를 검색 하고 발굴 할 수 있 는 것 이 아니 라 상호작용 식 계기판 을 통 해 데이터 집합 기능 을 제공한다.사용자 가 데이터 에 깊이 들 어가 키 워드 를 추가 하고 사용자 정의 조 회 를 사용 하면 모든 그림 이 실시 간 으로 업 데 이 트 됩 니 다. 이것 이 바로 facet 취 합 작업 방식 입 니 다.계기판 에는 데이터 가 정기 적 으로 계 산 된 정적 스냅 샷 이 아니 라 데이터 탐색 에 사용 되 는 진정한 상호작용 도구 이다.
본 논문 에서 우 리 는 ES 에서 데 이 터 를 어떻게 얻 은 다음 에 이런 도 표를 어떻게 만 드 는 지 배 울 것 이다.
관계 집합 (terms facet) 의 떡 그림 첫 번 째 그림 은 ES 에서 비교적 간단 한 termsfacet 로 만 듭 니 다.이 facet 는 필드 에서 가장 흔히 볼 수 있 는 단어 와 그 계수 값 을 되 돌려 줍 니 다.
우선 우 리 는 먼저 데 이 터 를 삽입 합 니 다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
curl -X DELETE "http://localhost:9200/dashboard"
curl -X POST "http://localhost:9200/dashboard/article" -d '
             { "title" : "One",
               "tags"  : ["ruby", "java", "search"]}
'
curl -X POST "http://localhost:9200/dashboard/article" -d '
             { "title" : "Two",
               "tags"  : ["java", "search"] }
'
curl -X POST "http://localhost:9200/dashboard/article" -d '
             { "title" : "Three",
               "tags"  : ["erlang", "search"] }
'
curl -X POST "http://localhost:9200/dashboard/article" -d '
             { "title" : "Four",
               "tags"  : ["search"] }
'
curl -X POST "http://localhost:9200/dashboard/_refresh"

보시 다시 피 저 희 는 글 의 라벨 을 저장 하고 있 습 니 다. 글 마다 여러 개의 라벨 을 저장 할 수 있 습 니 다. 데 이 터 는 JSON 형식 으로 보 낼 수 있 습 니 다. 이것 도 ES 의 문서 형식 입 니 다.
현재 문서 의 10 대 탭 을 알 고 싶 으 면 간단 한 요청 만 하면 됩 니 다.
1
2
3
4
5
6
7
8
curl -X POST "http://localhost:9200/dashboard/_search?pretty=true" -d '
{
    "query" : { "match_all" : {} },
    "facets" : {
        "tags" : { "terms" : {"field" : "tags", "size" : 10} }
    }
}
'

보 셨 습 니까? 저 는 모든 문 서 를 받 아들 이 고 terms facet 를 'tags' 라 고 정의 합 니 다.이 요청 은 다음 과 같은 데 이 터 를 되 돌려 줍 니 다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
    "took" : 2,
    // ... snip ...
    "hits" : {
        "total" : 4,
        // ... snip ...
    },
    "facets" : {
        "tags" : {
            "_type" : "terms",
            "missing" : 1,
            "terms" : [
                { "term" : "search", "count" : 4 },
                { "term" : "java",   "count" : 2 },
                { "term" : "ruby",   "count" : 1 },
                { "term" : "erlang", "count" : 1 }
            ]
        }
    }
}

JSON 에서 facets 부분 은 우리 의 관심 사 입 니 다. 특히 facets. tags. terms 배열 입 니 다.이것 은 우리 에 게 네 편의 글 에 search 태그, 두 편의 자바 태그 등 을 쳤 다 는 것 을 알려 줍 니 다.
이런 비례 유형의 데이터 에 가장 적합 한 시각 화 방안 은 바로 떡 그림 이나 그 변형: 도넛 그림 이다.Protovis 의 데이터 시각 화 도구 모음 을 사용 할 것 입 니 다.Protovis 는 100% 오픈 소스 입 니 다. 데이터 시각 화 방면 의 RoR 이 라 고 상상 할 수 있 습 니 다.다른 유사 한 도구 와 선명 한 대 조 를 이 루 는 것 은 '선택' 을 위 한 아이콘 형식 이 추가 되 어 있 지 않다 는 것 이다.원 어 와 유연 한 DSL 을 정의 하여 사용자 정의 시각 화 를 간단하게 만 들 수 있 습 니 다.떡 그림 을 만 드 는 것 은 매우 간단 하 다.
ES 가 JSON 데 이 터 를 되 돌려 주기 때문에 우 리 는 Ajax 호출 을 통 해 그것 을 불 러 올 수 있 습 니 다.클론 이나 인 스 턴 스 를 다운로드 할 수 있 는 모든 소스 코드 를 잊 지 마 세 요.
먼저 아이콘 을 수용 하기 위해 HTML 파일 이 필요 합 니 다. 그리고 ES 에서 데 이 터 를 불 러 옵 니 다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<!DOCTYPE html>
<html>
<head>
    <title>ElasticSearch Terms Facet Donut Chart</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <!-- Load JS libraries -->
    <script src="jquery-1.5.1.min.js"></script>
    <script src="protovis-r3.2.js"></script>
    <script src="donut.js"></script>
    <script>
        $( function() { load_data(); });
        var load_data = function() {
            $.ajax({   url: 'http://localhost:9200/dashboard/article/_search?pretty=true'
                     , type: 'POST'
                     , data : JSON.stringify({
                           "query" : { "match_all" : {} },
                           "facets" : {
                               "tags" : {
                                   "terms" : {
                                       "field" : "tags",
                                       "size"  : "10"
                                   }
                               }
                           }
                       })
                     , dataType : 'json'
                     , processData: false
                     , success: function(json, statusText, xhr) {
                           return display_chart(json);
                       }
                     , error: function(xhr, message, error) {
                           console.error("Error while loading data from ElasticSearch", message);
                           throw(error);
                       }
            });
            var display_chart = function(json) {
                Donut().data(json.facets.tags.terms).draw();
            };
        };
    </script>
</head>
<body>
  <!-- Placeholder for the chart -->
  <div id="chart"></div>
</body>
</html>

문 서 를 불 러 온 후, 우 리 는 Ajax 를 통 해 이전 curl 테스트 와 같은 facet 를 받 았 습 니 다.jQuery 의 Ajaxcallback 에서 봉 인 된 displaychart () 는 돌아 온 JSON 을 Donut () 함수 에 전달 합 니 다.
Donut () 함수 및 설명 은 다음 과 같 습 니 다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
var Donut = function(dom_id) {
    if ('undefined' == typeof dom_id)  {                // Set the default DOM element ID to bind
        dom_id = 'chart';
    }
    var data = function(json) {                         // Set the data for the chart
        this.data = json;
        return this;
    };
    var draw = function() {
        var entries = this.data.sort( function(a, b) {  // Sort the data by term names, so the
            return a.term < b.term ? -1 : 1;            // color scheme for wedges is preserved
        }),                                             // with any order
        values  = pv.map(entries, function(e) {         // Create an array holding just the counts
            return e.count;
        });
        // console.log('Drawing', entries, values);
        var w = 200,                                    // Dimensions and color scheme for the chart
            h = 200,
            colors = pv.Colors.category10().range();
        var vis = new pv.Panel()                        // Create the basis panel
            .width(w)
            .height(h)
            .margin(0, 0, 0, 0);
        vis.add(pv.Wedge)                               // Create the "wedges" of the chart
            .def("active", -1)                          // Auxiliary variable to hold mouse over state
            .data( pv.normalize(values) )               // Pass the normalized data to Protovis
            .left(w/3)                                  // Set-up chart position and dimension
            .top(w/3)
            .outerRadius(w/3)
            .innerRadius(15)                            // Create a "donut hole" in the center
            .angle( function(d) {                       // Compute the "width" of the wedge
                return d * 2 * Math.PI;
             })
            .strokeStyle("#fff")                        // Add white stroke
            .event("mouseover", function() {            // On "mouse over", set the "wedge" as active
                this.active(this.index);
                this.cursor('pointer');
                return this.root.render();
             })
            .event("mouseout",  function() {            // On "mouse out", clear the active state
                this.active(-1);
                return this.root.render();
            })
            .event("mousedown", function(d) {           // On "mouse down", perform action,
                var term = entries[this.index].term;    // such as filtering the results...
                return (alert("Filter the results by '"+term+"'"));
            })
            .anchor("right").add(pv.Dot)                // Add the left part of he "inline" label,
                                                        // displayed inside the donut "hole"
            .visible( function() {                      // The label is visible when its wedge is active
                return this.parent.children[0]
                       .active() == this.index;
            })
            .fillStyle("#222")
            .lineWidth(0)
            .radius(14)
            .anchor("center").add(pv.Bar)               // Add the middle part of the label
            .fillStyle("#222")
            .width(function(d) {                        // Compute width:
                return (d*100).toFixed(1)               // add pixels for percents
                              .toString().length*4 +
                       10 +                             // add pixels for glyphs (%, etc)
                       entries[this.index]              // add pixels for letters (very rough)
                           .term.length*9;
            })
            .height(28)
            .top((w/3)-14)
            .anchor("right").add(pv.Dot)                // Add the right part of the label
            .fillStyle("#222")
            .lineWidth(0)
            .radius(14)
            .parent.children[2].anchor("left")          // Add the text to label
                   .add(pv.Label)
            .left((w/3)-7)
            .text(function(d) {                         // Combine the text for label
                return (d*100).toFixed(1) + "%" +
                       ' ' + entries[this.index].term +
                       ' (' + values[this.index] + ')';
            })
            .textStyle("#fff")
            .root.canvas(dom_id)                        // Bind the chart to DOM element
            .render();                                  // And render it.
    };
    return {                                            // Create the public API
        data   : data,
        draw   : draw
    };
};

이제 보시 다시 피 간단 한 JSON 데이터 변환 을 통 해 우 리 는 풍부 하고 매력 적 인 글 태그 분포 에 대한 시각 화 아이콘 을 만 들 수 있 습 니 다.완전한 예 는 여기에 있다.
특정한 작가 의 글 을 표시 하거나 특정한 날짜 에 발표 한 글 을 표시 하 는 등 전혀 다른 요 구 를 사용 하면 전체 시각 화 는 정상적으로 작 동 하고 코드 는 다시 사용 할 수 있 습 니 다.
날짜 직사 도 (date histogram facets) 타임 라인 Protovis 는 다른 일반적인 시각 화 형식 을 만 드 는 것 도 매우 쉽다. 타임 라인.모든 유형의 데 이 터 는 특정한 날짜 와 관련 된 것, 예 를 들 어 글 발표, 사건 발생, 목표 달성 등 이 있 으 면 시간 선 으로 시각 화 될 수 있다.자, 발표 날짜 가 있 는 글 을 색인 에 저장 합 시다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
curl -X DELETE "http://localhost:9200/dashboard"
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "1",  "published" : "2011-01-01" }'
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "2",  "published" : "2011-01-02" }'
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "3",  "published" : "2011-01-02" }'
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "4",  "published" : "2011-01-03" }'
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "5",  "published" : "2011-01-04" }'
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "6",  "published" : "2011-01-04" }'
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "7",  "published" : "2011-01-04" }'
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "8",  "published" : "2011-01-04" }'
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "9",  "published" : "2011-01-10" }'
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "10", "published" : "2011-01-12" }'
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "11", "published" : "2011-01-13" }'
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "12", "published" : "2011-01-14" }'
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "13", "published" : "2011-01-14" }'
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "14", "published" : "2011-01-15" }'
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "15", "published" : "2011-01-20" }'
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "16", "published" : "2011-01-20" }'
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "17", "published" : "2011-01-21" }'
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "18", "published" : "2011-01-22" }'
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "19", "published" : "2011-01-23" }'
curl -X POST "http://localhost:9200/dashboard/article" -d '{ "t" : "20", "published" : "2011-01-24" }'
curl -X POST "http://localhost:9200/dashboard/_refresh"

우 리 는 ES 의 date histogram facet 로 글 발표 빈 도 를 얻 습 니 다.
1
2
3
4
5
6
7
8
9
10
11
12
13
curl -X POST "http://localhost:9200/dashboard/_search?pretty=true" -d '
{
    "query" : { "match_all" : {} },
    "facets" : {
        "published_on" : {
            "date_histogram" : {
                "field"    : "published",
                "interval" : "day"
            }
        }
    }
}
'

우리 가 어떻게 간격 을 하늘 로 설정 하 는 지 주의 하 세 요.이것 은 쉽게 주, 월, 혹은 년 으로 바 꿀 수 있다.
요청 은 아래 와 같은 JSON 으로 돌아 갑 니 다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
    "took" : 2,
    // ... snip ...
    "hits" : {
        "total" : 4,
        // ... snip ...
    },
    "facets" : {
        "published" : {
            "_type" : "histogram",
            "entries" : [
                { "time" : 1293840000000, "count" : 1 },
                { "time" : 1293926400000, "count" : 2 }
                // ... snip ...
            ]
        }
    }
}

우리 가 주의해 야 할 것 은 facets. published. entries 배열 입 니 다. 위의 예 와 같 습 니 다.아이콘 과 데 이 터 를 불 러 올 수 있 는 HTML 페이지 가 필요 합 니 다.메커니즘 이 같은 이상 코드 는 바로 여 기 를 보 세 요.
JSON 데이터 가 있 으 니 protovis 로 타임 라인 을 만 드 는 것 은 간단 합 니 다. 사용자 정의 area chart 를 사용 하면 됩 니 다.
주석 이 있 는 타임 라인 () 함 수 는 다음 과 같 습 니 다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
var Timeline = function(dom_id) {
    if ('undefined' == typeof dom_id) {                 // Set the default DOM element ID to bind
        dom_id = 'chart';
    }
    var data = function(json) {                         // Set the data for the chart
        this.data = json;
        return this;
    };
    var draw = function() {
        var entries = this.data;                        // Set-up the data
            entries.push({                              // Add the last "blank" entry for proper
              count : entries[entries.length-1].count   // timeline ending
            });
        // console.log('Drawing, ', entries);
        var w = 600,                                    // Set-up dimensions and scales for the chart
            h = 100,
            max = pv.max(entries, function(d) {return d.count;}),
            x = pv.Scale.linear(0, entries.length-1).range(0, w),
            y = pv.Scale.linear(0, max).range(0, h);
        var vis = new pv.Panel()                        // Create the basis panel
            .width(w)
            .height(h)
            .bottom(20)
            .left(20)
            .right(40)
            .top(40);
         vis.add(pv.Label)                              // Add the chart legend at top left
            .top(-20)
            .text(function() {
                 var first = new Date(entries[0].time);
                 var last  = new Date(entries[entries.length-2].time);
                 return "Articles published between " +
                     [ first.getDate(),
                       first.getMonth() + 1,
                       first.getFullYear()
                     ].join("/") +
                     " and " +
                     [ last.getDate(),
                       last.getMonth() + 1,
                       last.getFullYear()
                     ].join("/");
             })
            .textStyle("#B1B1B1")
         vis.add(pv.Rule)                               // Add the X-ticks
            .data(entries)
            .visible(function(d) {return d.time;})
            .left(function() { return x(this.index); })
            .bottom(-15)
            .height(15)
            .strokeStyle("#33A3E1")
            .anchor("right").add(pv.Label)              // Add the tick label (DD/MM)
            .text(function(d) {
                 var date = new Date(d.time);
                 return [
                     date.getDate(),
                     date.getMonth() + 1
                 ].join('/');
             })
            .textStyle("#2C90C8")
            .textMargin("5")
         vis.add(pv.Rule)                               // Add the Y-ticks
            .data(y.ticks(max))                         // Compute tick levels based on the "max" value
            .bottom(y)
            .strokeStyle("#eee")
            .anchor("left").add(pv.Label)
                .text(y.tickFormat)
                .textStyle("#c0c0c0")
        vis.add(pv.Panel)                               // Add container panel for the chart
           .add(pv.Area)                                // Add the area segments for each entry
           .def("active", -1)                           // Auxiliary variable to hold mouse state
           .data(entries)                               // Pass the data to Protovis
           .bottom(0)
           .left(function(d) {return x(this.index);})   // Compute x-axis based on scale
           .height(function(d) {return y(d.count);})    // Compute y-axis based on scale
           .interpolate('cardinal')                     // Make the chart curve smooth
           .segmented(true)                             // Divide into "segments" (for interactivity)
           .fillStyle("#79D0F3")
           .event("mouseover", function() {             // On "mouse over", set segment as active
               this.active(this.index);
               return this.root.render();
           })
           .event("mouseout",  function() {             // On "mouse out", clear the active state
               this.active(-1);
               return this.root.render();
           })
           .event("mousedown", function(d) {            // On "mouse down", perform action,
               var time = entries[this.index].time;     // eg filtering the results...
               return (alert("Timestamp: '"+time+"'"));
           })
           .anchor("top").add(pv.Line)                  // Add thick stroke to the chart
           .lineWidth(3)
           .strokeStyle('#33A3E1')
           .anchor("top").add(pv.Dot)                   // Add the circle "label" displaying
                                                        // the count for this day
           .visible( function() {                       // The label is only visible when
               return this.parent.children[0]           // its segment is active
                          .active() == this.index;
            })
           .left(function(d) { return x(this.index); })
           .bottom(function(d) { return y(d.count); })
           .fillStyle("#33A3E1")
           .lineWidth(0)
           .radius(14)
           .anchor("center").add(pv.Label)             // Add text to the label
           .text(function(d) {return d.count;})
           .textStyle("#E7EFF4")
           .root.canvas(dom_id)                        // Bind the chart to DOM element
           .render();                                  // And render it.
    };
    return {                                            // Create the public API
        data   : data,
        draw   : draw
    };
};

전체 예제 코드 는 여기에 있 습 니 다.그러나 먼저 protovis 가 제공 하 는 area 에 관 한 원본 문 서 를 다운로드 한 다음 에 interpolate (cardinal) 를 interpolate (step - after) 로 수정 한 후에 무슨 일이 일 어 났 는 지 관찰 하 세 요.여러 facet 에 대해 중 첩 된 구역 도 를 그리고 상호작용 을 추가 한 다음 에 완전히 맞 춤 형 가시 화 는 문제 가 되 지 않 을 것 이다.
중요 한 것 은 이 도표 가 ES 에 전달 한 요구 에 따라 응답 하여 특정한 지표의 시각 화 수 요 를 간단하게 완성 할 수 있 음 을 주의 하 는 것 이다.예 를 들 어 '이 작가 가 이 주제 에서 최근 3 개 월 동안 의 출판 빈 도 를 나타 낸다' 는 것 이다.이러한 요청 만 제출 하면 됩 니 다.
1
author:John AND topic:Search AND published:[2011-03-01 TO 2011-05-31]

요약 하면 복잡 한 사용자 정의 조 회 를 위해 풍부 한 상호작용 데이터 시각 화 를 해 야 할 때 ES 의 facets 를 사용 하 는 것 이 가장 쉬 운 방법 중 하나 일 것 입 니 다. ES 의 JSON 응답 을 Protovis 와 같은 도구 에 전달 하면 됩 니 다.
본 논문 의 방법 과 코드 를 모방 함으로써 너 는 몇 시간 안에 너의 데 이 터 를 예 로 들 수 있다.
REFERENECE :  http://www.chepoo.com/elasticsearch-protovis.html | IT 기술 정화 망  

좋은 웹페이지 즐겨찾기