10

MongoDB に保存している一部のデータで少し問題が発生しました (注: ODM として mongoose を使用しています)。私は2つのスキーマを持っています:

mongoose.model('Buyer',{
  credit: Number,
})

mongoose.model('Item',{
  bid: Number,
  location: { type: [Number], index: '2d' }
})

バイヤー/アイテムには、1 対多の関係を持つ親子関係があります。Item を Buyer ドキュメントにサブドキュメントとして埋め込むように設定したり、オブジェクト ID を相互に参照する 2 つの別個のドキュメントを作成したりできることを知っています。

私が直面している問題は、入札額がバイヤーのクレジットよりも低いだけでなく、場所が特定の地理座標に近いアイテムをクエリする必要があることです。

最初の基準を満たすには、Items をサブドキュメントとして埋め込んで、2 つの数値を比較できるようにする必要があるようです。しかし、位置を geoNear クエリで比較するには、ドキュメントを分離したほうがよいようです。そうしないと、各サブドキュメントで geoNear を実行できません。

このデータに対して両方のタスクを実行できる方法はありますか? その場合、どのようにデータを構造化すればよいですか? そうでない場合、1 つのクエリを実行してから、最初のクエリの結果に対して 2 番目のクエリを実行する方法はありますか?

ご協力いただきありがとうございます!

4

2 に答える 2

3

階層をmongodbに保存するための別のオプション(埋め込みと正規化以外)があります。つまり、ツリー構造として保存します。この場合、Buyers と Item を別々のドキュメントに保存しますが、同じコレクションに保存します。各 Item ドキュメントには、その Buyer (親) ドキュメントを指すフィールドが必要であり、各 Buyer ドキュメントの親フィールドは null に設定されます。選択できるいくつかの実装を説明するためにリンクしたドキュメント。

于 2015-05-06T23:25:44.413 に答える
2

アイテムが 2 つの別々のコレクションに格納されている場合、最適なオプションは独自の関数を作成し、それを使用して呼び出すことmongoose.connection.db.eval('some code...');です。このような場合、高度なロジックをサーバー側で実行できます。

次のように書くことができます。

var allNearItems = db.Items.find(
    { location: {
        $near: {
            $geometry: {
              type: "Point" ,
              coordinates: [ <longitude> , <latitude> ]
            },
            $maxDistance: 100
        }
    }
}); 
var res = [];
allNearItems.forEach(function(item){
    var buyer = db.Buyers.find({ id: item.buyerId })[0];
    if (!buyer) continue;
    if (item.bid < buyer.credit) {
        res.push(item.id);
    }
});
return res;

評価後 (mongoose.connection.db.eval("...")呼び出しに配置)、アイテム ID の配列を取得します。

注意して使用してください。allNearItems 配列が大きすぎるか、非常に頻繁にクエリを実行すると、パフォーマンスの問題に直面する可能性があります。実際、MongoDB チームは js コードの直接実行を非推奨にしましたが、現在の安定版リリースでは引き続き利用できます。

于 2015-05-12T15:07:35.137 に答える