2

これは私のアイテムモデルです。配列をフィルタリングするときに空の配列を含める方法

const itemSchema = new Schema({ 
    name: String, 
    category: String, 
    occupied: [Number], 
    active: { type: Boolean, default: true }, 
}); 

「占有」の配列をフィルタリングしたいですか?だから私は集計を使用し、 '占有'フィールドを巻き戻します。

だから私は一致クエリを適用します。 _idでグループ化する。 フィルタされた '占有'配列が空の場合、項目は消えます。ここで

は私のコードここ

Item.aggregate([ 
    { $match: { 
    active: true 
    }}, 
    { $unwind: 
    "$occupied", 
    }, 
    { $match: { $and: [ 
    { occupied: { $gte: 100 }}, 
    { occupied: { $lt: 200 }} 
    ]}}, 
    { $group : { 
    _id: "$_id", 
    name: { $first: "$name"}, 
    category: { $first: "$category"}, 
    occupied: { $addToSet : "$occupied" } 
    }} 
], (err, items) => { 
    if (err) throw err; 
    return res.json({ data: items }); 
}); 

は、例えば、データが

{ 
    "_id" : ObjectId("59c1bced987fa30b7421a3eb"), 
    "name" : "printer1", 
    "category" : "printer", 
    "occupied" : [ 95, 100, 145, 200 ], 
    "active" : true 
}, 
{ 
    "_id" : ObjectId("59c2dbed992fb91b7421b1ad"), 
    "name" : "printer2", 
    "category" : "printer", 
    "occupied" : [ ], 
    "active" : true 
} 

クエリ

[ 
    { 
    "_id" : ObjectId("59c1bced987fa30b7421a3eb"), 
    "name" : "printer1", 
    "category" : "printer", 
    "occupied" : [ 100, 145 ], 
    "active" : true 
    } 
] 

と私は

[ 
    { 
    "_id" : ObjectId("59c1bced987fa30b7421a3eb"), 
    "name" : "printer1", 
    "category" : "printer", 
    "occupied" : [ 100, 145 ], 
    "active" : true 
    }, 
    { 
    "_id" : ObjectId("59c2dbed992fb91b7421b1ad"), 
    "name" : "printer2", 
    "category" : "printer", 
    "occupied" : [ ], 
    "active" : true 
    } 
] 
を望む結果上記の結果を設定されています210

どうすればいいですか?

ありがとうございます。

+1

あなたが持っているデータの明確な例、あなたが望む結果、およびあなたが持っている試みを提供する限りでは、データサンプルのための「かわいい」オプションを見つけたことが望ましいでしょうそれを達成するために作られた、多くの多くの人々は実際にここで質問をする方法をあなたから学ぶことができます。これは正確にどのように質問するべきかです。ポイントと完全に。がんばり続ける。 –

+0

@NeilLunnコメントありがとうございました。私はそれを念頭に置くでしょう。 – 125487

答えて

0

最も簡単な形式では、まず$unwindを使用しないでください。適用される条件は、特定の値との一致の「ユニークなセット」を探していることを意味します。

あなたの代わりに $filterを使用し、このために

、そして最初の場所で「設定」に入力値を減らすために$setUnionのような「設定演算子」:そう

Item.aggregate([ 
    { "$match": { "active": true } }, 
    { "$project": { 
    "name": 1, 
    "category": 1, 
    "occupied": { 
     "$filter": { 
     "input": { "$setUnion": [ "$occupied", []] }, 
     "as": "o", 
     "cond": { 
      "$and": [ 
      { "$gte": ["$$o", 100 ] }, 
      { "$lt": ["$$o", 200] } 
      ] 
     } 
     } 
    } 
    }} 
], (err, items) => { 
    if (err) throw err; 
    return res.json({ data: items }); 
}); 

両方がMongoDBのv3のため、回避されています、このようにするのはかなり一般的な方法です。

Item.aggregate([ 
    { "$match": { "active": true } }, 
    { "$project": { 
    "name": 1, 
    "category": 1, 
    "occupied": { 
     "$setDifference": [ 
     { "$map": { 
      "input": "$occupied", 
      "as": "o", 
      "in": { 
      "$cond": { 
       "if": { 
       "$and": [ 
        { "$gte": ["$$o", 100 ] }, 
        { "$lt": ["$$o", 200] } 
       ] 
       }, 
       "then": "$$o", 
       "else": false 
      } 
      } 
     }}, 
     [false] 
     ] 
    } 
    }} 
], (err, items) => { 
    if (err) throw err; 
    return res.json({ data: items }); 
}); 

をそれは、離れて配列を引っ張っアイテムをフィルタリングして置くと同じ「固有のセット」の結果です:あなたはまだのMongoDB 2.6を使用していたいくつかの理由で、その後、あなたが代わりに$map$setDifferenceを適用することができれば

一緒に戻って$addToSetと一緒に。違いは、はるかに効率的であり、何の問題もなく空の配列を保持(または生成)することです。

+0

私は今MongoDB 2.6を使用しています。しかし、私はv3をアップデートし、あなたの解決策を試してみましょう。詳細な説明をありがとう。 – 125487

+0

@ 125487答えで述べたように、2番目の方法は、MongoDB 2.6と互換性のある演算子を使用する方法です。私はあなたが公式のサポートを望むなら、[そのバージョンはサポートのために人生を過ぎています](https://www.mongodb.com/support-policy)であることに注意してください。アップグレードはおそらくあなたの最大の利益になります。 –

+0

MongoDBをv3.4にアップデートしました。あなたの最初のアプローチは完全に機能します。コメントありがとう。 – 125487

関連する問題