0

次のドキュメントを含むコレクションがあります。

{
"_id" : ObjectId("51f1fd2b8188d3117c6da352"),
"cust_id" : "abc1234",
"ord_date" : ISODate("2012-10-03T18:30:00Z"),
"status" : "A",
"price" : 27,
"items" : [{
  "sku" : "mmm",
  "qty" : 5,
  "price" : 2.5
}, {
  "sku" : "nnn",
  "qty" : 5,
  "price" : 2.5
}]
}

「アイテム」のフィールドで「$where」を使用したいので、のようにします。

{$where:"this.items.sku==mmm"} 

どうすればいいですか?フィールドが配列型でない場合に機能します。

4

3 に答える 3

2

$whereこれを行うためにオペレーターは必要ありません。次のクエリ オブジェクトを使用するだけです。

{ "items.sku": mmm }

機能しない理由については、その演算子の値が JavaScript として実行されるため、配列$whereの各要素をチェックするのではなく、通常のオブジェクトとして扱い、そのプロパティ (未定義) を比較するだけです。 .itemsitemsskummm

于 2013-07-27T04:20:50.920 に答える
0

質問に加えて、あなたのコメントを読んでいます。ドキュメント内の配列に保存している属性を、ユーザーが一般的に追加できるようです。クライアントは、一般的な方法でドキュメントから任意のペアをクエリできる必要があります。これを実現するためのパターンは通常、次のとおりです。

 {
    .
    .
    attributes:[
     {k:"some user defined key",
      v:"the value"},
     {k: ,v:}
      .
      .
    ]
 }

あなたの場合、アイテムは属性であることに注意してください。ドキュメントを取得するには、クエリは次のようになります。

eg)
db.collection.find({attributes:{$elemMatch:{k:"sku",v:"mmm"}}});
(index attributes.k, attributes.v)

これにより、サービスはデータをクエリする方法を提供し、クライアントが k,v ペアが何であるかを指定できるようになります。この設計に関する 1 つの注意点は、ドキュメントには 16MB の制限があることに常に注意することです (GridFS を適切にするユースケースがない限り)。これを制御するのに役立つ $slice のような関数があります。

于 2013-07-27T19:48:50.687 に答える
0

初期化されていないため、値を持つthis.items.skuvariableと比較しています。やりたいことは、配列を反復し、各エントリを string と比較することです。この例では、渡された関数がエントリの少なくとも 1 つを返した場合に、を返す配列メソッドsomeを使用してこれを行います。mmmunefined'mmm'truetrue

{$where:"return this.items.some(function(entry){return entry.sku =='mmm'})"} 

しかし、本当に、これをしないでください。JohnnyHK の回答に対するコメントで、「私のサービスはユーザーと mongodb の間の単なるインターフェイスであり、フィールド クライアントが何を格納したいのかをまったく認識していません」と述べています。ユースケースを実際に説明しているわけではありませんが、これをより適切に解決できると確信しています。

  • $where 演算子は、この簡単な式が通常のクエリで実行できる場合でも、Javascript エンジンを呼び出します。これは、不要なパフォーマンス オーバーヘッドを意味します。
  • コレクション内のすべてのドキュメントが関数に渡されるため、インデックスがある場合は使用できません。
  • クライアントから提供されたものから JavaScript 関数が生成される場合、適切にサネット化してエスケープするように注意する必要があります。そうしないと、アプリケーションがコード インジェクションに対して脆弱になります。
于 2013-07-27T05:26:32.143 に答える