2013-04-05 2 views
2

에서 첫 번째 항목을 일치하는 문서를 검색 :MongoDB를/Mongoid : 나는 배열이 문서가 배열

{ 
    _id: ObjectId("515e10784903724d72000003"), 
    association_chain: [ 
     { 
      name: "Product", 
      id: ObjectId("4e1e2cdd9a86652647000003") 
     } 
    ], 
    //... 
} 

내가 문서 컬렉션을 검색하기 위해 노력하고있어이 곳의 첫 번째 항목의 nameassociation_chain 배열이 주어진 값과 일치합니다.

Mongoid를 사용하여 어떻게 할 수 있습니까? 또는 MongoDB를 사용하여이 작업을 수행하는 방법 만 알고 있다면 예제를 게시하면 Mongoid를 사용하여 작업하는 방법을 알아낼 수 있습니다.

답변

2

두 가지 방법 :

1) 당신이 이미 알고있는 경우를 당신이 "association_chain"에 나오는 첫 번째 제품 이름에만 관심이있어, 다음이 더 나은 :

db.items.find("association_chain.0.name":"something") 

'association_chain'배열의 첫 번째 위치에서 원하는 제품을 언급 한 항목 만 반환하는 것은 아닙니다.

이 작업을 수행하려면, 다음 인덱스가 필요합니다 : 당신이 특정 제품을 찾고 있습니다,하지만 당신이 확실하지 않은 경우

db.items.ensureIndex({"association_chain.0.name":1},{background:1}) 

2) association_chain의 어느 위치에가 나타납니다 다음을 수행하십시오 :

MongoDB 쉘을 사용하면 중첩 된 구조 내의 모든 해시 키에 '.' 도트 연산자! 이것은 키가 레코드에 중첩되어 있다는 것과는 관계가 없습니다 (멋지지 않습니까?)

이 같은 해시의 내장 배열에 발견 할 수 있습니다 :

db.items.find("association_chain.name":"something") 

이것은 association_array 어디서나 언급 원하는 제품을 포함하는 컬렉션의 모든 레코드를 반환합니다.

이 작업을 수행하려면, 당신은 당신이 인덱스가 있는지 확인해야합니다

db.items.ensureIndex({"association_chain.name":1},{background: 1}) 

이 페이지의 "점 표기법"을 참조하십시오 : http://docs.mongodb.org/manual/core/document/

+0

두 번째 코드 블록은 '.find'가 아닌 'db.items.ensureIndex'여야합니다. –

+0

참으로 - catch 덕분입니다! – Tilo

1

집계 프레임 워크에서이를 수행 할 수 있습니다. mongo 쉘에서 문서를 푸는 쿼리를 실행하여 배열 요소 당 문서 (다른 필드에 중복 된 데이터가 있음)를 포함시킨 다음, id 및 포함시킬 다른 필드별로 그룹화하고 $ first 연산자 . 그런 다음 $ match 연산자를 포함하여 이름이나 mongoid별로 필터링합니다.

다음은 첫 번째 제품의 이름과 일치하는 쿼리의 :

db.foo.aggregate([ 
{ $unwind:"$association_chain"  
}, 
{ 
    $group : { 
      "_id" : { 
       "_id" : "$_id", 
       "other" : "$other" 
      }, 
      "association_chain" : { 
       $first : "$association_chain" 
      } 
     } 
}, 
{ $match:{ "association_chain.name":"Product"} 
} 

]) 

여기 mongoid에 의해 첫 번째 제품에 대한 쿼리하는 방법은 다음과 같습니다

db.foo.aggregate([ 
{ $unwind:"$association_chain"  
}, 
{ 
    $group : { 
      "_id" : { 
       "_id" : "$_id", 
       "other" : "$other" 
      }, 
      "association_chain" : { 
       $first : "$association_chain" 
      } 
     } 
}, 
{ $match:{ "association_chain.id":ObjectId("4e1e2cdd9a86652647000007")} 
} 

]) 
+0

I로 집계 프레임 워크를 사용 사이의 차이를 Dot Notation을 사용하여 간단한 쿼리를 사용하거나 언급 한 경우 Dot Notation을 사용하면 배열 association_chain의 모든 요소를 ​​포함한 전체 문서가 반환됩니다. 이 쿼리를 집계와 함께 사용하면 배열의 첫 번째 요소와 일치하는 요소 만있는 문서를 반환하거나 원하는 방식으로 문서를 변형 할 수 있습니다. 귀하의 필요에 가장 적합한 것을 사용하십시오. – AntonioOtero

5

는 위치 연산자를 사용합니다. 배열의 첫 번째 요소를 .0 (그리고 두 번째 요소는 .1 등)으로 쿼리 할 수 ​​있습니다.

당신은 위치 운영자가 히트를 반환하지 않는 두 번째 요소에 foo 검색부터 적용되는 것을 볼 수 있습니다
> db.items.insert({association_chain: [{name: 'foo'}, {name: 'bar'}]}) 
> db.items.find({"association_chain.0.name": "foo"}) 
{ "_id" : ObjectId("516348865862b60b7b85d962"), "association_chain" : [ { "name" : "foo" }, { "name" : "bar" } ] } 

...

> db.items.find({"association_chain.1.name": "foo"}) 
> 

...하지만 bar 검색은 않습니다.

> db.items.find({"association_chain.1.name": "bar"}) 
{ "_id" : ObjectId("516348865862b60b7b85d962"), "association_chain" : [ { "name" : "foo" }, { "name" : "bar" } ] } 

당신이 할 수있는 모든 연결 체인 문서의 모든 이름 색인이없는 경우에도 색인이 특정 필드 :

> db.items.ensureIndex({"association_chain.0.name": 1}) 
> db.items.find({"association_chain.0.name": "foo"}).explain() 
{ 
     "cursor" : "BtreeCursor association_chain.0.name_1", 
     "nscanned" : 1, 
     ... 

} 
> db.items.find({"association_chain.1.name": "foo"}).explain() 
{ 
     "cursor" : "BasicCursor", 
     "nscanned" : 3, 
     ... 
} 
이 할
+1

나는 이런 식으로 색인을 남용 할 줄은 몰랐습니다. 그것을 사랑해. – pestilence669