summaryrefslogtreecommitdiff
path: root/jstests/core/geo_center_sphere1.js
blob: f3b39b552cd1984e725b0a85f27c02a629cbed1a (plain)
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
t = db.geo_center_sphere1;

function test(index) {
    t.drop();
    skip = 8;  // lower for more rigor, higher for more speed (tested with .5, .678, 1, 2, 3, and 4)

    searches = [
        //  x , y    rad
        [[5, 0], 0.05],  // ~200 miles
        [[135, 0], 0.05],

        [[5, 70], 0.05],
        [[135, 70], 0.05],
        [[5, 85], 0.05],

        [[20, 0], 0.25],  // ~1000 miles
        [[20, -45], 0.25],
        [[-20, 60], 0.25],
        [[-20, -70], 0.25],
    ];
    correct = searches.map(function(z) {
        return [];
    });

    num = 0;

    var bulk = t.initializeUnorderedBulkOp();
    for (x = -179; x <= 179; x += skip) {
        for (y = -89; y <= 89; y += skip) {
            o = {
                _id: num++,
                loc: [x, y]
            };
            bulk.insert(o);
            for (i = 0; i < searches.length; i++) {
                if (Geo.sphereDistance([x, y], searches[i][0]) <= searches[i][1])
                    correct[i].push(o);
            }
        }
        gc();  // needed with low skip values
    }
    assert.writeOK(bulk.execute());

    if (index) {
        t.ensureIndex({loc: index});
    }

    for (i = 0; i < searches.length; i++) {
        print('------------');
        print(tojson(searches[i]) + "\t" + correct[i].length);
        q = {
            loc: {$within: {$centerSphere: searches[i]}}
        };

        // correct[i].forEach( printjson )
        // printjson( q );
        // t.find( q ).forEach( printjson )

        // printjson(t.find( q ).explain())

        // printjson( Array.sort( correct[i].map( function(z){ return z._id; } ) ) )
        // printjson( Array.sort( t.find(q).map( function(z){ return z._id; } ) ) )

        var numExpected = correct[i].length;
        var x = correct[i].map(function(z) {
            return z._id;
        });
        var y = t.find(q).map(function(z) {
            return z._id;
        });

        missing = [];
        epsilon = 0.001;  // allow tenth of a percent error due to conversions
        for (var j = 0; j < x.length; j++) {
            if (!Array.contains(y, x[j])) {
                missing.push(x[j]);
                var obj = t.findOne({_id: x[j]});
                var dist = Geo.sphereDistance(searches[i][0], obj.loc);
                print("missing: " + tojson(obj) + " " + dist);
                if ((Math.abs(dist - searches[i][1]) / dist) < epsilon)
                    numExpected -= 1;
            }
        }
        for (var j = 0; j < y.length; j++) {
            if (!Array.contains(x, y[j])) {
                missing.push(y[j]);
                var obj = t.findOne({_id: y[j]});
                var dist = Geo.sphereDistance(searches[i][0], obj.loc);
                print("extra: " + tojson(obj) + " " + dist);
                if ((Math.abs(dist - searches[i][1]) / dist) < epsilon)
                    numExpected += 1;
            }
        }

        assert.eq(numExpected, t.find(q).itcount(), "itcount : " + tojson(searches[i]));
        assert.eq(numExpected, t.find(q).count(), "count : " + tojson(searches[i]));
        if (index == "2d") {
            var explain = t.find(q).explain("executionStats");
            print('explain for ' + tojson(q, '', true) + ' = ' + tojson(explain));
            // The index should be at least minimally effective in preventing the full collection
            // scan.
            assert.gt(t.find().count(),
                      explain.executionStats.totalKeysExamined,
                      "nscanned : " + tojson(searches[i]));
        }
    }
}

test("2d");
test("2dsphere");
test(false);