2017-12-25 26 views
0

私はこのような部屋スキーマを持っています。 イベントスキーマ:照会文書は

let eventSchema = new mongoose.Schema({ 
    title: { type: String, required: true }, 
    room: { type: mongoose.Schema.ObjectId, ref: 'Room', required: true }, 
    date: { type: Date, required: true }, 
    slot: { type: Number, required: true } 
}); 

私がやろうとしています何が、次のとおりです。
「クエリ特定スロットのイベントが含まれていないすべての客室に、」。

リクエストの日付が部屋の日付とスロットに一致する場合、その部屋は応答には含まれません。フィールドの1つだけが一致した場合、それは応答内にあるはずです。

私はここに同様の質問を見つけましたが、私のシナリオのどれも:
https://stackoverflow.com/a/36371665/5115768
Mongoose query where value is not null

は、私のような何かをしようとしたん:

this.model.find(req.query).populate({ 
    path: 'events', 
    match: { 
    date: { $ne: req.query.date }, 
    slot: { $ne: req.query.slot } 
    } 
}).exec((err, rooms) => { 

    rooms = rooms.filter((room) => { 
    return room.events != null; 
    }); 

    res.status(200).json(rooms); 
}); 

しかし、もちろん、それは、部屋は常にある(動作しません。空の配列)。これは本当に苦労しています。

サブ文書(イベント)に基づく条件で文書(室)をクエリするにはどうすればよいですか?

UPDATE

slotはもう配列でないように、私は自分のスキーマとコードを変更しました。

私が@ Veeramの解決策を正しく理解していれば、予約された部屋のために空の配列eventsを返すので、使用できません。この問題は、空のevents配列を持つこれらの部屋をフィルタリングする必要があることです。最初の場所にイベントが関連付けられていない部屋も含まれます(フィルタリングしないでください)。

今、私はすべての「予約された部屋」(req.query.datereq.query.slotに一致するイベントが含まれているもの)を得ることができた:

this.model.find(req.query).populate({ 
    path: 'events', 
    match: { 
    $and: [ 
     { date: { $eq: date } }, 
     { slot: { $eq: slot } } 
    ] 
    } 
}).exec((err, reservedRooms) => { 
    reservedRooms = reservedRooms.filter(room => room.events.length > 0); 
    res.status(200).json(reservedRooms); 
}); 

どのように、これは私が何をしたいの正反対であるが、それはスタートですそれを "逆"にすることはできますか?

+1

移入は、任意の一致なしで動作を確認した後 '一致してみてください:{ 日:{$ NE:req.query.date}、 スロット:{$ニン:[req.query.slot]} を}'。それが動作すれば、空のイベント配列を出力します。一致しない場合は空のチェックイベント配列に基づいてルームをフィルタリングできます。 – Veeram

+0

ちょっと助けられましたが、完全にはわかりません。**アップデート** – lenny

+0

申し訳ありませんが、私は明確ではなく、すべてのケースをカバーしませんでした。存在しないイベントの場合、あなたはイベントフィールドを部屋に持たないので、そこには何も配置されず、イベントフィールドもそこにはありません。存在するイベントについては、一致する条件に基づいて一致するイベントが入力されます。例えば;イベントがない '{room:" room1 "}"、一致するイベントがなく、{{room: "room3"、イベント:[{date:2017、title: "event1"]} 'と一致するイベント。だから本質的に出力が戻ってきたら、イベント配列が存在するすべての部屋を表示するだけです。 – Veeram

答えて

0

を取り込み、イベント、アレイ内の各イベントのための一致基準を適用します。

イベント配列の各要素に否定を適用すると、イベントが発生した配列(一致)と、配列が取得されたときに利用可能なイベントがない(一致しない)配列との区別が失われます。

したがって、サーバ$lookupを使用して、配列全体に条件を適用する必要があります。

以下の集計クエリは、イベント(存在する場合)にクエリで指定された日付とスロットのドキュメントが含まれていない部屋をフィルタリングします。

$elemMatchを使用して同じ要素のクエリ条件を比較し、$notを使用して、配列要素にクエリ条件が含まれていない部屋を返します。

this.model.aggregate([ 
    { 
    "$match":{"events":{"$exist":true}} 
    }, 
    { 
    "$lookup": { 
     "from": "events", // Collection name not model or schema name 
     "localField": "events", 
     "foreignField": "_id", 
     "as": "events" 
    } 
    }, 
    { 
    "$match":{"$not":{"$elemMatch":{"date": date, "slot":slot}}} 
    } 
]).exec((err, reservedRooms) => {}); 

イベントを含む会議室を出力します。除外を伴う$projectを使用して、最終出力からイベントを削除することができます。最終段階として{$project:{"events":0}}を加える。

+0

これは私に正しい結果を得られません。依然として基準に合致するイベントを含む部屋を得る。 – lenny

+0

私が作成したテストデータで動作するようです。テストのためにいくつかのデータを提供してください。 – Veeram

0

あなたが試してみました:

match: { 
    $not: [{ 
     $and: [ 
      date: { $eq: req.query.date }, 
      slot: { $in: req.query.slot } 
     ] 
    }] 
} 
+0

、部屋の配列は常に空です。 – lenny

+0

愚かな質問ですが、質問を更新したので、 '$ in'を' $ eq'に更新しようとしましたか? –

+0

はい、私のコメントも間違っていました。あなたのコードは 'unknown top level operator:$ not'を返します。 – lenny

関連する問題