2016-07-20 3 views
0

관계를 사용하여 MySQL 데이터베이스에서 Elastic Search 지리적 거리 쿼리를 만들고 싶습니다. 위치 데이터가있는 표가 한 개 있고 위치 표와 관계가있는 다른 표가 있습니다. Elastic Search와 같은 NoSQL 데이터베이스는 이와 같은 관계에 맞게 최적화되지 않았지만 가능합니까?Elastic Search MySQL 관계가있는 지리적 거리 쿼리

이이처럼 내 데이터베이스 스키마 모습입니다 :

CREATE TABLE `locations` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `description` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `lng` decimal(12,8) NOT NULL, 
    `lat` decimal(12,8) NOT NULL, 
    `deleted_at` timestamp NULL DEFAULT NULL, 
    `created_at` timestamp NULL DEFAULT NULL, 
    `updated_at` timestamp NULL DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

CREATE TABLE `posts` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `author` int(10) unsigned NOT NULL, 
    `location_id` int(10) unsigned NOT NULL, 
    `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `text` text COLLATE utf8_unicode_ci NOT NULL, 
    `deleted_at` timestamp NULL DEFAULT NULL, 
    `created_at` timestamp NULL DEFAULT NULL, 
    `updated_at` timestamp NULL DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `posts_author_foreign` (`author`), 
    KEY `posts_location_id_foreign` (`location_id`), 
    CONSTRAINT `posts_author_foreign` FOREIGN KEY (`author`) REFERENCES `users` (`id`), 
    CONSTRAINT `posts_location_id_foreign` FOREIGN KEY (`location_id`) REFERENCES `locations` (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=174 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

CREATE TABLE `comments` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `post_id` int(10) unsigned NOT NULL, 
    `author` int(10) unsigned NOT NULL, 
    `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `text` text COLLATE utf8_unicode_ci NOT NULL, 
    `deleted_at` timestamp NULL DEFAULT NULL, 
    `created_at` timestamp NULL DEFAULT NULL, 
    `updated_at` timestamp NULL DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `comments_author_foreign` (`author`), 
    KEY `comments_post_id_foreign` (`post_id`), 
    CONSTRAINT `comments_author_foreign` FOREIGN KEY (`author`) REFERENCES `users` (`id`), 
    CONSTRAINT `comments_post_id_foreign` FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=238 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

가 여기 내 인덱스 매핑입니다 (내가 사용하는 official Elasticsearch client for PHP) :

<?php 
return [ 
    'index' => 'foodie', 
    'body' => [ 
     'mappings' => [ 
      'locations' => [ 
       'properties' => [ 
        'id' => ['type' => 'string', 'index' => 'not_analyzed'], 
        'name' => ['type' => 'string'], 
        'description' => ['type' => 'string'], 
        'location' => ['type' => 'geo_point'], 
       ], 
      ], 
      'posts' => [ 
       'properties' => [ 
        'id' => ['type' => 'string', 'index' => 'not_analyzed'], 
        'author' => ['type' => 'string', 'index' => 'not_analyzed'], 
        'location_id' => ['type' => 'string', 'index' => 'not_analyzed'], 
        'title' => ['type' => 'string'], 
        'text' => ['type' => 'string'], 
       ], 
      ], 
      'comments' => [ 
       'properties' => [ 
        'id' => ['type' => 'string', 'index' => 'not_analyzed'], 
        'author' => ['type' => 'string', 'index' => 'not_analyzed'], 
        'post_id' => ['type' => 'string', 'index' => 'not_analyzed'], 
        'title' => ['type' => 'string'], 
        'text' => ['type' => 'string'], 
       ], 
      ] 
     ], 
     'settings' => [ 
      'analysis' => [ 
       'filter' => [ 
       ], 
       'analyzer' => [ 
       ], 
      ], 
     ], 
    ], 
]; 

나는 위치와 게시물에 대한 쿼리를하고 싶습니다 (그리고 주석 (= 두 개의 조인 거리)은 성능면에서 나쁘지 않은 경우), 필자는 지리적 거리별로 필터링하고 정렬 할 수 있습니다.

나는이 같은 쿼리를 시도 :

[ 
    'index' => 'index_name', 
    'type' => [ 
     0 => 'posts', 
     1 => 'locations', 
     2 => 'comments' 
    ], 
    'body' => [ 
     'from' => 0, 
     'size' => 10, 
     'query' => [ 
      'bool' => [ 
       'must' => [ 
        'multi_match' => [ 
         'query' => 'search string', 
         'fields' => [ 
          0 => 'title', 
          1 => 'text', 
          2 => 'name', 
          3 => 'description', 
         ], 
         'fuzziness' => 'AUTO', 
         'operator' => 'and', 
        ], 
       ], 
       'filter' => [ 
        'geo_distance' => [ 
         'distance' => '100m', 
         'location' => [ 
          'lat' => 79.861, 
          'lon' => 107.31, 
         ], 
        ], 
       ], 
      ], 
     ], 
    ], 
] 

그것은 위치 데이터가 위치를 제외한 모든 필터링 분명히 작동하지만. 관련 게시물 및 심지어 주석을 쿼리에 포함하려면 어떻게합니까?

감사합니다.

+1

언급했듯이 대부분의 NoSQL 데이터 저장소는 관계형 모델을 피하는 경향이 있습니다. 그러나 어쨌든 관계형 모델을 적용하려고합니다. 문서 데이터 저장소 (예 : MongoDB 및 Elasticsearch)는 데이터를 [denormalizing] (https://en.wikipedia.org/wiki/Denormalization)하여 번창하므로 한 곳만 볼 수 있습니다. 데이터에 효과적으로 참여하여 단일 문서에 덤프하면 (게시물에 주석 배열이 있음) 원하는 결과를 얻을 수 있습니다. 또는 게시물이있는 부모/자식 문서를 부모로, 어린이를 주석으로 표시 할 수 있습니다. – pickypg

+0

네, 입력 해 주셔서 감사합니다. 나는 데이터를 비정규 화하는 것이 나를위한 좋은 해결책이라고 생각한다. – Pelmered

답변

0

나는 이것을 수행하기위한 좋은 해결책을 찾지 못했지만 단순히 포스트와 코멘트에 위치 필드를 추가 한 다음 Elasticsearch 인덱스에 밀어 넣을 때 관련 위치의 좌표를 가져 와서 해결했습니다.

아마도 최적의 해결책은 아니지만 잘 작동하며 인덱스가 완전히 평평하게 유지되면 매우 빠릅니다. 위치 좌표의 변경 사항이 관련 게시물 및 주석으로 전달되는지 여부를 확인하기 만하면 중복 된 데이터를 인덱스에 저장하는 것이 그렇게 깨끗하지는 않다는 점을 제외하고는이 접근법에 실제 문제는 없습니다.