1
0
Fork 0

fix example, so geo indices are actually used (#6305)

This commit is contained in:
Wilfried Goesgens 2018-08-30 19:22:13 +02:00 committed by Frank Celler
parent fd81e34498
commit a30a93aa3f
10 changed files with 217 additions and 185 deletions

View File

@ -9,68 +9,91 @@ We use [the city graph](../../Manual/Graphs/index.html#the-city-graph) and its g
![Cities Example Graph](../../Manual/Graphs/cities_graph.png)
@startDocuBlockInline COMBINING_GRAPH_01_create_graph
@EXAMPLE_ARANGOSH_OUTPUT{COMBINING_GRAPH_01_create_graph}
~addIgnoreCollection("germanHighway");
~addIgnoreCollection("germanCity");
~addIgnoreCollection("frenchHighway");
~addIgnoreCollection("frenchCity");
~addIgnoreCollection("internationalHighway");
var examples = require("@arangodb/graph-examples/example-graph.js");
var g = examples.loadGraph("routeplanner");
var bonn=[7.0998, 50.7340];
|db._query(`FOR startCity IN germanCity
| FILTER GEO_DISTANCE(@bonn, startCity) < @radius
| RETURN startCity`,
| { bonn: bonn, radius: 400000 }
).toArray()
~examples.dropGraph("routeplanner");
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock COMBINING_GRAPH_01_create_graph
We search all german cities in a range of 400 km around the ex-capital **Bonn**: **Hamburg** and **Cologne**.
We won't find **Paris** since its in the `frenchCity` collection.
@startDocuBlockInline COMBINING_GRAPH_02_combine
@EXAMPLE_ARANGOSH_OUTPUT{COMBINING_GRAPH_02_combine}
var bonn=[7.0998, 50.7340];
|db._query(`FOR startCity IN germanCity
| FILTER GEO_DISTANCE(@bonn, startCity) < @radius
| FOR v, e, p IN 1..1 OUTBOUND startCity
| GRAPH 'routeplanner'
| RETURN {startcity: startCity._key, traversedCity: v}`,
| { bonn: bonn, radius: 400000 }
).toArray();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock COMBINING_GRAPH_02_combine
@startDocuBlockInline COMBINING_GRAPH_02_show_geo
@EXAMPLE_AQL{COMBINING_GRAPH_02_show_geo}
@DATASET{routeplanner}
FOR startCity IN germanCity
FILTER GEO_DISTANCE(@bonn, startCity.geometry) < @radius
RETURN startCity._key
@BV {
bonn: [7.0998, 50.7340],
radius: 400000
}
@END_EXAMPLE_AQL
@endDocuBlock COMBINING_GRAPH_02_show_geo
The geo index query returns us `startCity` (**Cologne** and **Hamburg**) which we then use as starting point for our graph traversal. For simplicity we only return their direct neighbours. We format the return result so we can see from which `startCity` the traversal came.
Lets revalidate that the geo indices are actually used:
@startDocuBlockInline COMBINING_GRAPH_03_explain_geo
@EXAMPLE_AQL{COMBINING_GRAPH_03_explain_geo}
@DATASET{routeplanner}
@EXPLAIN{TRUE}
FOR startCity IN germanCity
FILTER GEO_DISTANCE(@bonn, startCity.geometry) < @radius
RETURN startCity._key
@BV {
bonn: [7.0998, 50.7340],
radius: 400000
}
@END_EXAMPLE_AQL
@endDocuBlock COMBINING_GRAPH_03_explain_geo
And now combine this with a graph traversal:
@startDocuBlockInline COMBINING_GRAPH_04_combine
@EXAMPLE_AQL{COMBINING_GRAPH_04_combine}
@DATASET{routeplanner}
FOR startCity IN germanCity
FILTER GEO_DISTANCE(@bonn, startCity.geometry) < @radius
FOR v, e, p IN 1..1 OUTBOUND startCity
GRAPH 'routeplanner'
RETURN {startcity: startCity._key, traversedCity: v._key}
@BV {
bonn: [7.0998, 50.7340],
radius: 400000
}
@END_EXAMPLE_AQL
@endDocuBlock COMBINING_GRAPH_04_combine
The geo index query returns us `startCity` (**Cologne** and **Hamburg**) which we then use as starting point for our graph traversal.
For simplicity we only return their direct neighbours. We format the return result so we can see from which `startCity` the traversal came.
Alternatively we could use a `LET` statement with a subquery to group the traversals by their `startCity` efficiently:
@startDocuBlockInline COMBINING_GRAPH_03_combine_let
@EXAMPLE_ARANGOSH_OUTPUT{COMBINING_GRAPH_03_combine_let}
~var bonn=[50.7340, 7.0998];
|db._query(`FOR startCity IN germanCity
| FILTER GEO_DISTANCE(@bonn, startCity) < @radius
| LET oneCity = (FOR v, e, p IN 1..1 OUTBOUND startCity
| GRAPH 'routeplanner' RETURN v)
| return {startCity: startCity._key, connectedCities: oneCity}`,
| { bonn: bonn, radius: 400000 }
).toArray();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock COMBINING_GRAPH_03_combine_let
@startDocuBlockInline COMBINING_GRAPH_05_combine_let
@EXAMPLE_AQL{COMBINING_GRAPH_05_combine_let}
@DATASET{routeplanner}
FOR startCity IN germanCity
FILTER GEO_DISTANCE(@bonn, startCity.geometry) < @radius
LET oneCity = (
FOR v, e, p IN 1..1 OUTBOUND startCity
GRAPH 'routeplanner' RETURN v._key
)
RETURN {startCity: startCity._key, connectedCities: oneCity}
@BV {
bonn: [7.0998, 50.7340],
radius: 400000
}
@END_EXAMPLE_AQL
@endDocuBlock COMBINING_GRAPH_05_combine_let
Finally, we clean up again:
@startDocuBlockInline COMBINING_GRAPH_04_cleanup
@EXAMPLE_ARANGOSH_OUTPUT{COMBINING_GRAPH_04_cleanup}
@startDocuBlockInline COMBINING_GRAPH_06_cleanup
@EXAMPLE_ARANGOSH_OUTPUT{COMBINING_GRAPH_06_cleanup}
~var examples = require("@arangodb/graph-examples/example-graph.js");
~var g = examples.loadGraph("routeplanner");
examples.dropGraph("routeplanner");
~removeIgnoreCollection("germanHighway");
~removeIgnoreCollection("germanCity");
~removeIgnoreCollection("frenchHighway");
~removeIgnoreCollection("frenchCity");
~removeIgnoreCollection("internationalHighway");
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock COMBINING_GRAPH_04_cleanup
@endDocuBlock COMBINING_GRAPH_06_cleanup

View File

@ -1,34 +1,2 @@
arangosh&gt; <span class="hljs-keyword">var</span> examples = <span class="hljs-built_in">require</span>(<span class="hljs-string">"@arangodb/graph-examples/example-graph.js"</span>);
arangosh&gt; <span class="hljs-keyword">var</span> g = examples.loadGraph(<span class="hljs-string">"routeplanner"</span>);
arangosh&gt; <span class="hljs-keyword">var</span> bonn=[<span class="hljs-number">7.0998</span>, <span class="hljs-number">50.7340</span>];
arangosh&gt; db._query(<span class="hljs-string">`FOR startCity IN germanCity
........&gt; FILTER GEO_DISTANCE(@bonn, startCity) &lt; @radius
........&gt; RETURN startCity`</span>,
........&gt; { <span class="hljs-attr">bonn</span>: bonn, <span class="hljs-attr">radius</span>: <span class="hljs-number">400000</span> }
........&gt; ).toArray()
[
{
<span class="hljs-string">"_key"</span> : <span class="hljs-string">"Cologne"</span>,
<span class="hljs-string">"_id"</span> : <span class="hljs-string">"germanCity/Cologne"</span>,
<span class="hljs-string">"_rev"</span> : <span class="hljs-string">"_XWXBCQG--B"</span>,
<span class="hljs-string">"population"</span> : <span class="hljs-number">1000000</span>,
<span class="hljs-string">"isCapital"</span> : <span class="hljs-literal">false</span>,
<span class="hljs-string">"type"</span> : <span class="hljs-string">"Point"</span>,
<span class="hljs-string">"coordinates"</span> : [
<span class="hljs-number">6.9528</span>,
<span class="hljs-number">50.9364</span>
]
},
{
<span class="hljs-string">"_key"</span> : <span class="hljs-string">"Hamburg"</span>,
<span class="hljs-string">"_id"</span> : <span class="hljs-string">"germanCity/Hamburg"</span>,
<span class="hljs-string">"_rev"</span> : <span class="hljs-string">"_XWXBCQG--D"</span>,
<span class="hljs-string">"population"</span> : <span class="hljs-number">1000000</span>,
<span class="hljs-string">"isCapital"</span> : <span class="hljs-literal">false</span>,
<span class="hljs-string">"type"</span> : <span class="hljs-string">"Point"</span>,
<span class="hljs-string">"coordinates"</span> : [
<span class="hljs-number">10.0014</span>,
<span class="hljs-number">53.5653</span>
]
}
]

View File

@ -1,85 +0,0 @@
arangosh&gt; <span class="hljs-keyword">var</span> bonn=[<span class="hljs-number">7.0998</span>, <span class="hljs-number">50.7340</span>];
arangosh&gt; db._query(<span class="hljs-string">`FOR startCity IN germanCity
........&gt; FILTER GEO_DISTANCE(@bonn, startCity) &lt; @radius
........&gt; FOR v, e, p IN 1..1 OUTBOUND startCity
........&gt; GRAPH 'routeplanner'
........&gt; RETURN {startcity: startCity._key, traversedCity: v}`</span>,
........&gt; { <span class="hljs-attr">bonn</span>: bonn, <span class="hljs-attr">radius</span>: <span class="hljs-number">400000</span> }
........&gt; ).toArray();
[
{
<span class="hljs-string">"startcity"</span> : <span class="hljs-string">"Cologne"</span>,
<span class="hljs-string">"traversedCity"</span> : {
<span class="hljs-string">"_key"</span> : <span class="hljs-string">"Lyon"</span>,
<span class="hljs-string">"_id"</span> : <span class="hljs-string">"frenchCity/Lyon"</span>,
<span class="hljs-string">"_rev"</span> : <span class="hljs-string">"_XWXBCQK--_"</span>,
<span class="hljs-string">"population"</span> : <span class="hljs-number">80000</span>,
<span class="hljs-string">"isCapital"</span> : <span class="hljs-literal">false</span>,
<span class="hljs-string">"type"</span> : <span class="hljs-string">"Point"</span>,
<span class="hljs-string">"coordinates"</span> : [
<span class="hljs-number">4.84</span>,
<span class="hljs-number">45.76</span>
]
}
},
{
<span class="hljs-string">"startcity"</span> : <span class="hljs-string">"Cologne"</span>,
<span class="hljs-string">"traversedCity"</span> : {
<span class="hljs-string">"_key"</span> : <span class="hljs-string">"Paris"</span>,
<span class="hljs-string">"_id"</span> : <span class="hljs-string">"frenchCity/Paris"</span>,
<span class="hljs-string">"_rev"</span> : <span class="hljs-string">"_XWXBCQK--B"</span>,
<span class="hljs-string">"population"</span> : <span class="hljs-number">4000000</span>,
<span class="hljs-string">"isCapital"</span> : <span class="hljs-literal">true</span>,
<span class="hljs-string">"type"</span> : <span class="hljs-string">"Point"</span>,
<span class="hljs-string">"coordinates"</span> : [
<span class="hljs-number">2.3508</span>,
<span class="hljs-number">48.8567</span>
]
}
},
{
<span class="hljs-string">"startcity"</span> : <span class="hljs-string">"Hamburg"</span>,
<span class="hljs-string">"traversedCity"</span> : {
<span class="hljs-string">"_key"</span> : <span class="hljs-string">"Cologne"</span>,
<span class="hljs-string">"_id"</span> : <span class="hljs-string">"germanCity/Cologne"</span>,
<span class="hljs-string">"_rev"</span> : <span class="hljs-string">"_XWXBCQG--B"</span>,
<span class="hljs-string">"population"</span> : <span class="hljs-number">1000000</span>,
<span class="hljs-string">"isCapital"</span> : <span class="hljs-literal">false</span>,
<span class="hljs-string">"type"</span> : <span class="hljs-string">"Point"</span>,
<span class="hljs-string">"coordinates"</span> : [
<span class="hljs-number">6.9528</span>,
<span class="hljs-number">50.9364</span>
]
}
},
{
<span class="hljs-string">"startcity"</span> : <span class="hljs-string">"Hamburg"</span>,
<span class="hljs-string">"traversedCity"</span> : {
<span class="hljs-string">"_key"</span> : <span class="hljs-string">"Paris"</span>,
<span class="hljs-string">"_id"</span> : <span class="hljs-string">"frenchCity/Paris"</span>,
<span class="hljs-string">"_rev"</span> : <span class="hljs-string">"_XWXBCQK--B"</span>,
<span class="hljs-string">"population"</span> : <span class="hljs-number">4000000</span>,
<span class="hljs-string">"isCapital"</span> : <span class="hljs-literal">true</span>,
<span class="hljs-string">"type"</span> : <span class="hljs-string">"Point"</span>,
<span class="hljs-string">"coordinates"</span> : [
<span class="hljs-number">2.3508</span>,
<span class="hljs-number">48.8567</span>
]
}
},
{
<span class="hljs-string">"startcity"</span> : <span class="hljs-string">"Hamburg"</span>,
<span class="hljs-string">"traversedCity"</span> : {
<span class="hljs-string">"_key"</span> : <span class="hljs-string">"Lyon"</span>,
<span class="hljs-string">"_id"</span> : <span class="hljs-string">"frenchCity/Lyon"</span>,
<span class="hljs-string">"_rev"</span> : <span class="hljs-string">"_XWXBCQK--_"</span>,
<span class="hljs-string">"population"</span> : <span class="hljs-number">80000</span>,
<span class="hljs-string">"isCapital"</span> : <span class="hljs-literal">false</span>,
<span class="hljs-string">"type"</span> : <span class="hljs-string">"Point"</span>,
<span class="hljs-string">"coordinates"</span> : [
<span class="hljs-number">4.84</span>,
<span class="hljs-number">45.76</span>
]
}
}
]

View File

@ -0,0 +1,17 @@
@Q:
FOR startCity IN germanCity
FILTER GEO_DISTANCE(@bonn, startCity.geometry) &lt; @radius
RETURN startCity._key
@B
{
<span class="hljs-string">"bonn"</span>: [
<span class="hljs-number">7.0998</span>,
<span class="hljs-number">50.734</span>
],
<span class="hljs-string">"radius"</span>: <span class="hljs-number">400000</span>
}
@R
[
<span class="hljs-string">"Cologne"</span>,
<span class="hljs-string">"Hamburg"</span>
]

View File

@ -1,8 +0,0 @@
arangosh&gt; db._query(<span class="hljs-string">`FOR startCity IN germanCity
........&gt; FILTER GEO_DISTANCE(@bonn, startCity) &lt; @radius
........&gt; LET oneCity = (FOR v, e, p IN 1..1 OUTBOUND startCity
........&gt; GRAPH 'routeplanner' RETURN v)
........&gt; return {startCity: startCity._key, connectedCities: oneCity}`</span>,
........&gt; { <span class="hljs-attr">bonn</span>: bonn, <span class="hljs-attr">radius</span>: <span class="hljs-number">400000</span> }
........&gt; ).toArray();
[ ]

View File

@ -0,0 +1,39 @@
@Q:
FOR startCity IN germanCity
FILTER GEO_DISTANCE(@bonn, startCity.geometry) &lt; @radius
RETURN startCity._key
@B
{
<span class="hljs-string">"bonn"</span>: [
<span class="hljs-number">7.0998</span>,
<span class="hljs-number">50.734</span>
],
<span class="hljs-string">"radius"</span>: <span class="hljs-number">400000</span>
}
@R
<span style="color:rgb(85,85,255)">Query String:</span>
<span style="color:rgb(0,187,0)"> FOR startCity IN germanCity
FILTER GEO_DISTANCE(@bonn, startCity.geometry) &lt; @radius
RETURN startCity._key
</span>
<span style="color:rgb(85,85,255)">Execution plan:</span>
<span style="color:rgb(187,0,187)">Id</span> <span style="color:rgb(187,0,187)">NodeType</span> <span style="color:rgb(187,0,187)">Est.</span> <span style="color:rgb(187,0,187)">Comment</span>
<span style="color:rgb(187,187,0)">1</span> <span style="color:rgb(0,187,187)">SingletonNode</span> <span style="color:rgb(0,187,0)">1</span> * <span style="color:rgb(0,187,187)">ROOT</span>
<span style="color:rgb(187,187,0)">7</span> <span style="color:rgb(0,187,187)">IndexNode</span> <span style="color:rgb(0,187,0)">3</span> - <span style="color:rgb(0,187,187)">FOR</span> <span style="color:rgb(187,187,0)">startCity</span> <span style="color:rgb(0,187,187)">IN</span> <span style="color:rgb(187,0,0)">germanCity</span> <span style="color:rgb(0,0,187)">/* geo index scan</span> */
<span style="color:rgb(187,187,0)">5</span> <span style="color:rgb(0,187,187)">CalculationNode</span> <span style="color:rgb(0,187,0)">3</span> - <span style="color:rgb(0,187,187)">LET</span> <span style="color:rgb(187,0,187)">#3</span> = <span style="color:rgb(187,187,0)">startCity</span>.`<span style="color:rgb(187,187,0)">_key</span>` <span style="color:rgb(0,0,187)">/* attribute expression */</span> <span style="color:rgb(0,0,187)">/* collections used:</span> <span style="color:rgb(187,187,0)">startCity</span> : <span style="color:rgb(187,0,0)">germanCity</span> <span style="color:rgb(0,0,187)">*/</span>
<span style="color:rgb(187,187,0)">6</span> <span style="color:rgb(0,187,187)">ReturnNode</span> <span style="color:rgb(0,187,0)">3</span> - <span style="color:rgb(0,187,187)">RETURN</span> <span style="color:rgb(187,0,187)">#3</span>
<span style="color:rgb(85,85,255)">Indexes used:</span>
<span style="color:rgb(187,0,187)">By</span> <span style="color:rgb(187,0,187)">Type</span> <span style="color:rgb(187,0,187)">Collection</span> <span style="color:rgb(187,0,187)">Unique</span> <span style="color:rgb(187,0,187)">Sparse</span> <span style="color:rgb(187,0,187)">Selectivity</span> <span style="color:rgb(187,0,187)">Fields</span> <span style="color:rgb(187,0,187)">Ranges</span>
<span style="color:rgb(187,187,0)">7</span> <span style="color:rgb(0,187,187)">geo</span> <span style="color:rgb(187,0,0)">germanCity</span> <span style="color:rgb(0,187,0)">false</span> <span style="color:rgb(0,187,0)">true</span> <span style="color:rgb(0,187,0)">n/a</span> [ `<span style="color:rgb(187,187,0)">geometry</span>` ] (<span style="color:rgb(0,187,0)">GEO_DISTANCE</span>([ <span style="color:rgb(0,187,0)">7.0998</span>, <span style="color:rgb(0,187,0)">50.734</span> ], <span style="color:rgb(187,187,0)">startCity</span>.`<span style="color:rgb(187,187,0)">geometry</span>`) &lt; <span style="color:rgb(0,187,0)">400000</span>)
<span style="color:rgb(85,85,255)">Optimization rules applied:</span>
<span style="color:rgb(187,0,187)">Id</span> <span style="color:rgb(187,0,187)">RuleName</span>
<span style="color:rgb(187,187,0)">1</span> <span style="color:rgb(0,187,187)">move-calculations-up</span>
<span style="color:rgb(187,187,0)">2</span> <span style="color:rgb(0,187,187)">move-filters-up</span>
<span style="color:rgb(187,187,0)">3</span> <span style="color:rgb(0,187,187)">move-calculations-up-2</span>
<span style="color:rgb(187,187,0)">4</span> <span style="color:rgb(0,187,187)">move-filters-up-2</span>
<span style="color:rgb(187,187,0)">5</span> <span style="color:rgb(0,187,187)">geo-index-optimizer</span>
<span style="color:rgb(187,187,0)">6</span> <span style="color:rgb(0,187,187)">remove-unnecessary-calculations-2</span>

View File

@ -0,0 +1,37 @@
@Q:
FOR startCity IN germanCity
FILTER GEO_DISTANCE(@bonn, startCity.geometry) &lt; @radius
FOR v, e, p IN <span class="hljs-number">1.</span><span class="hljs-number">.1</span> OUTBOUND startCity
GRAPH <span class="hljs-string">'routeplanner'</span>
RETURN {<span class="hljs-attr">startcity</span>: startCity._key, <span class="hljs-attr">traversedCity</span>: v._key}
@B
{
<span class="hljs-string">"bonn"</span>: [
<span class="hljs-number">7.0998</span>,
<span class="hljs-number">50.734</span>
],
<span class="hljs-string">"radius"</span>: <span class="hljs-number">400000</span>
}
@R
[
{
<span class="hljs-string">"startcity"</span>: <span class="hljs-string">"Cologne"</span>,
<span class="hljs-string">"traversedCity"</span>: <span class="hljs-string">"Lyon"</span>
},
{
<span class="hljs-string">"startcity"</span>: <span class="hljs-string">"Cologne"</span>,
<span class="hljs-string">"traversedCity"</span>: <span class="hljs-string">"Paris"</span>
},
{
<span class="hljs-string">"startcity"</span>: <span class="hljs-string">"Hamburg"</span>,
<span class="hljs-string">"traversedCity"</span>: <span class="hljs-string">"Cologne"</span>
},
{
<span class="hljs-string">"startcity"</span>: <span class="hljs-string">"Hamburg"</span>,
<span class="hljs-string">"traversedCity"</span>: <span class="hljs-string">"Paris"</span>
},
{
<span class="hljs-string">"startcity"</span>: <span class="hljs-string">"Hamburg"</span>,
<span class="hljs-string">"traversedCity"</span>: <span class="hljs-string">"Lyon"</span>
}
]

View File

@ -0,0 +1,34 @@
@Q:
FOR startCity IN germanCity
FILTER GEO_DISTANCE(@bonn, startCity.geometry) &lt; @radius
LET oneCity = (
FOR v, e, p IN <span class="hljs-number">1.</span><span class="hljs-number">.1</span> OUTBOUND startCity
GRAPH <span class="hljs-string">'routeplanner'</span> RETURN v._key
)
RETURN {<span class="hljs-attr">startCity</span>: startCity._key, <span class="hljs-attr">connectedCities</span>: oneCity}
@B
{
<span class="hljs-string">"bonn"</span>: [
<span class="hljs-number">7.0998</span>,
<span class="hljs-number">50.734</span>
],
<span class="hljs-string">"radius"</span>: <span class="hljs-number">400000</span>
}
@R
[
{
<span class="hljs-string">"startCity"</span>: <span class="hljs-string">"Cologne"</span>,
<span class="hljs-string">"connectedCities"</span>: [
<span class="hljs-string">"Lyon"</span>,
<span class="hljs-string">"Paris"</span>
]
},
{
<span class="hljs-string">"startCity"</span>: <span class="hljs-string">"Hamburg"</span>,
<span class="hljs-string">"connectedCities"</span>: [
<span class="hljs-string">"Cologne"</span>,
<span class="hljs-string">"Paris"</span>,
<span class="hljs-string">"Lyon"</span>
]
}
]

View File

@ -111,37 +111,44 @@ var createRoutePlannerGraph = function () {
_key: 'Berlin',
population: 3000000,
isCapital: true,
'type': 'Point',
'coordinates': [13.3833, 52.5167]
});
geometry: {
'type': 'Point',
'coordinates': [13.3833, 52.5167]
}});
var cologne = g.germanCity.save({
_key: 'Cologne',
population: 1000000,
isCapital: false,
'type': 'Point',
'coordinates': [6.9528, 50.9364]
});
geometry: {
'type': 'Point',
'coordinates': [6.9528, 50.9364]
}});
var hamburg = g.germanCity.save({
_key: 'Hamburg',
population: 1000000,
isCapital: false,
'type': 'Point',
'coordinates': [10.0014, 53.5653]
});
geometry: {
'type': 'Point',
'coordinates': [10.0014, 53.5653]
}});
var lyon = g.frenchCity.save({
_key: 'Lyon',
population: 80000,
isCapital: false,
'type': 'Point',
'coordinates': [4.8400, 45.7600]});
geometry: {
'type': 'Point',
'coordinates': [4.8400, 45.7600]
}});
var paris = g.frenchCity.save({
_key: 'Paris',
population: 4000000,
isCapital: true,
'type': 'Point',
'coordinates': [2.3508, 48.8567]});
g.germanCity.ensureIndex({ type: "geo", fields: [ "coordinates" ], geoJson:true });
g.frenchCity.ensureIndex({ type: "geo", fields: [ "coordinates" ], geoJson:true });
geometry: {
'type': 'Point',
'coordinates': [2.3508, 48.8567]
}});
g.germanCity.ensureIndex({ type: "geo", fields: [ "geometry" ], geoJson:true });
g.frenchCity.ensureIndex({ type: "geo", fields: [ "geometry" ], geoJson:true });
g.germanHighway.save(berlin._id, cologne._id, {distance: 850});
g.germanHighway.save(berlin._id, hamburg._id, {distance: 400});
g.germanHighway.save(hamburg._id, cologne._id, {distance: 500});