2016-06-18 6 views
2

私は2つのコレクションを持っています.1つはプロパティとして都市コードと緯度&経度を持つコレクションです。AQLで別名とソートされたクエリを返す

座標に最も近い都市を返したいと思います。これはジオインデックスでは簡単ですが、問題は同じ都市が複数回返されていることです。別の都市と接している郵便番号のために1番と3番に近いことがあります。

都市の例のデータ:

[ 
    { 
    "_key": "30936019", 
    "_id": "cities/30936019", 
    "_rev": "30936019", 
    "countryCode": "US", 
    "label": "Colorado Springs, CO", 
    "name": "Colorado Springs", 
    "postalCodes": [ 
     "80904", 
     "80927" 
    ], 
    "region": "CO" 
    }, 
    { 
    "_key": "30983621", 
    "_id": "cities/30983621", 
    "_rev": "30983621", 
    "countryCode": "US", 
    "label": "Manitou Springs, CO", 
    "name": "Manitou Springs", 
    "postalCodes": [ 
     "80829" 
    ], 
    "region": "CO" 
    } 
] 

postalCodes例データ:

[ 
    { 
    "_key": "32132856", 
    "_id": "postalCodes/32132856", 
    "_rev": "32132856", 
    "countryCode": "US", 
    "location": [ 
     38.9286, 
     -104.6583 
    ], 
    "postalCode": "80927" 
    }, 
    { 
    "_key": "32147422", 
    "_id": "postalCodes/32147422", 
    "_rev": "32147422", 
    "countryCode": "US", 
    "location": [ 
     38.8533, 
     -104.8595 
    ], 
    "postalCode": "80904" 
    }, 
    { 
    "_key": "32172144", 
    "_id": "postalCodes/32172144", 
    "_rev": "32172144", 
    "countryCode": "US", 
    "location": [ 
     38.855, 
     -104.9058 
    ], 
    "postalCode": "80829" 
    } 
] 

次のクエリでは、これを行うには、より効率的な方法があります場合、私は思ったんだけどArangoDB初心者としてではなく動作します

FOR p IN WITHIN(postalCodes, 38.8609, -104.8734, 30000, 'distance') 
    FOR c IN cities 
     FILTER p.postalCode IN c.postalCodes AND c.countryCode == p.countryCode 
     COLLECT close = c._id AGGREGATE distance = MIN(p.distance) 
     FOR c2 IN cities 
      FILTER c2._id == close 
      SORT distance 
      RETURN c2 

答えて

2

クエリの最初のFORは、ジオインデックスaを使用しますおそらく少数の文書(指定された場所の周りの郵便番号だけ)を返すでしょう。 2番目のFORは、見つけられた郵便番号ごとに都市を検索します。これは、cities.postalCodescities.countryCodeにインデックスが存在するかどうかによって、問題となる可能性があります。そうでなければ、2番目のFORは、それが関連するたびにcitiesコレクションのフルスキャンを実行する必要があります。これは非効率的です。したがって、このような二つの属性に索引を作成することができる。

db.cities.ensureIndex({ type: "hash", fields: ["countryCode", "postalCodes[*]"] });

c._idではなくcことではないCOLLECT INGとき第三FORを完全に削除することができます。

FOR p IN WITHIN(postalCodes, 38.8609, -104.8734, 30000, 'distance') 
    FOR c IN cities 
    FILTER p.postalCode IN c.postalCodes AND c.countryCode == p.countryCode 
    COLLECT city = c AGGREGATE distance = MIN(p.distance) 
    SORT distance 
    RETURN city 

これは短くなりますクエリの文字列、それはO(1)である都市の文書を検索するために、第3のFORがプライマリインデックスを使用するので、私が思うと効率を助けることができない場合があります。

一般に、インデックスを使用するクエリについて疑問がある場合は、db._explain(queryString)を使用してクエリで使用されるインデックスを表示できます。

関連する問題