1

イベントの開始時刻と座標を含むcouchdbがあります。次のように、現在の場所からそれらのイベントまでの距離を計算するリスト ビューを作成しました。

locateEvents: function(head, req){ 

        var row, comma = ''; 
        start({
            "headers": {
                "Content-Type": "application/json"
            }
        });
        if(req.query.latitude&&req.query.longitude&&req.query.radius&&req.query.now){

            var R = 6371; // km
            var dLon, dLat, lat1, lat2;

            var results = [];
            while(row = getRow()) { 
                dLon = Math.abs(row.value.venue.longitude-req.query.longitude);
                dLat = Math.abs(row.value.venue.latitude-req.query.latitude);

                dLon = (dLon*3.14159)/180;
                dLat = (dLat*3.14159)/180;

                lat1 = (Math.abs(req.query.longitude)*3.14159)/180;
                lat2 = (Math.abs(req.query.latitude)*3.14159)/180;

                var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
                Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2); 
                var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
                var d = R * c;

                if((d < req.query.radius)&&(row.value.start_time > req.query.now)){
                    results.push(row.value);
                }
            }
            send(JSON.stringify(results));
        }else{
            start({"code": 500});
            send("Latitude, longitude, page and radius parameters should be provided. i.e: latitude=value&longitude=value&radius=value&now=value");
        }

次のようなイベントの単純な byDate ビューがあります。

byDate: {
            map: function(doc){ if (doc.resource === 'Event') {emit(doc.venue.start_time, doc);}}
        }

私の懸念: 最初にリスト内の距離でイベントを並べ替えてから、並べ替えられたリストを開始時間で並べ替える方法はありますか?

4

1 に答える 1

0

私の理解が正しければ、最も近いイベントが最初に表示されることを望んでいます。同じ距離内に 2 つのイベントがある場合は、最も早いものを最初に表示します。

これは、オブジェクトを結果セットにプッシュする前に、計算された距離をオブジェクトに保存することで実行できます。

row.value._distance = d;
results.push(row);

アンダースコアで始まるすべてのフィールド_はcouchdbによって予約されているため、ドキュメントを保存できないことに注意してください。ただし、イベントまでの距離はリクエストごとに異なる可能性が高いため、問題ありません。ドキュメントをストアに保存する必要がある場合は、忘れずにプロパティを削除してください。

次のステップでは、イベントをソートする賢い方法を考え出す必要があります。これで、必要なすべての情報がドキュメントに保存されました。

JavaScript は複雑なデータ構造のソートをあまり好まないため、いくつかの調整を行う必要があります。

var sort = function(a,b) {
  if (JSON.stringify(a) == JSON.stringify(b)) return 0;
  return (JSON.stringify([a,b]) == JSON.stringify([a,b].sort())) ? -1 : 1
};

この関数は、単純な値の配列を次のように並べ替えるだけです。

> sort(["a",1], ["a", 0])
1

> sort(["a",0], ["a", 1])
-1

> sort(["a",0], ["a", 0])
0

楽しい部分として、send結果をクライアントに返す前に、それらを並べ替えます。

// ...
results.sort(function(a, b) {
  return sort(
    [a.value._distance, a.value.venue.start_time],
    [b.value._distance, b.value.venue.start_time]
  );
});

send(JSON.stringify(results));

例:

[{"value": {"_distance": 100, "venue": { "start_time": "Wed, 21 Mar 2012 04:31:24 -0700" } } },
 {"value": {"_distance": 212, "venue": { "start_time": "Sat, 13 Oct 2012 02:52:12 -0700" } } },
 {"value": {"_distance": 235, "venue": { "start_time": "Mon, 22 Jul 2013 12:50:20 -0700" } } },
 {"value": {"_distance": 677, "venue": { "start_time": "Thu, 09 May 2013 03:39:55 -0700" } } },
 {"value": {"_distance": 654, "venue": { "start_time": "Thu, 29 Sep 2011 15:31:46 -0700" } } },
 {"value": {"_distance": 100, "venue": { "start_time": "Tue, 20 Sep 2011 19:16:37 -0700" } } }]

sort上記の関数を使用すると、次のようになります。

[{"value": {"_distance": 100, "venue": {"start_time": "Tue, 20 Sep 2011 19:16:37 -0700" } } },
 {"value": {"_distance": 100, "venue": {"start_time": "Wed, 21 Mar 2012 04:31:24 -0700" } } },
 {"value": {"_distance": 212, "venue": {"start_time": "Sat, 13 Oct 2012 02:52:12 -0700" } } },
 {"value": {"_distance": 235, "venue": {"start_time": "Mon, 22 Jul 2013 12:50:20 -0700" } } },
 {"value": {"_distance": 654, "venue": {"start_time": "Thu, 29 Sep 2011 15:31:46 -0700" } } },
 {"value": {"_distance": 677, "venue": {"start_time": "Thu, 09 May 2013 03:39:55 -0700" } } }]

ソート後、最初の 2 つのオブジェクトが保持されます_distance == 100が、最初のオブジェクトの方が早いため、最初にソートされることに注意してください。

それが役立つことを願っています!

于 2012-08-29T21:05:58.327 に答える