특정 값을 포함하는 배열이있는 문서 찾기


499

이 스키마가 있다면 ...

person = {
    name : String,
    favoriteFoods : Array
}

... favoriteFoods어레이는 문자열로 채워집니다. 몽구스를 사용하여 좋아하는 음식으로 "초밥"을 가진 모든 사람을 어떻게 찾을 수 있습니까?

나는 다음 줄을 따라 무언가를 바랐다.

PersonModel.find({ favoriteFoods : { $contains : "sushi" }, function(...) {...});

( $containsmongodb에는 솔루션이 없다는 것을 알기 전에 찾을 것으로 예상되는 것을 설명하는 것이 없다는 것을 알고 있습니다)

답변:


693

favouriteFoods문자열의 간단한 배열입니다, 당신은 단지 해당 필드를 직접 조회 할 수 있습니다 :

PersonModel.find({ favouriteFoods: "sushi" }, ...);

그러나 스키마에서 문자열 배열을 명시 적으로 만드는 것이 좋습니다.

person = {
    name : String,
    favouriteFoods : [String]
}

관련 문서는 https://docs.mongodb.com/manual/tutorial/query-arrays/ 에서 찾을 수 있습니다.


19
다음과 같은 경우에도 작동합니다 favouriteFoods.favouriteFoods:[{type:Schema.Types.ObjectId, ref:'Food'}]
k88074

12
Mongo를 처음 접하는 사람이 MySQL과 같은 RDBMS에서 왔을 때 그러한 솔루션이 JOIN과 추가 테이블없이 간단하게 작동한다는 것을 알기 위해 Mongo를 더 일찍 시작하지 않은 이유가 궁금합니다. 그러나 DBMS가 다른 DBMS보다 우수하다는 것은 아닙니다. 사용 사례에 따라 다릅니다.
Irvin Lim

9
실수하지 마십시오. 그것이 dict의 목록 인 경우에도 여전히 이런 식으로 쿼리 할 수 ​​있습니다. 샘플 : PersonModel.find({ favouriteFoods.text: "sushi" }, ...); person = { name : String, favouriteFoods : [{text:String}] }
Aminah Nuraini

3
두 개 이상의 문자열이 포함 된 배열을 찾으려면 어떻게됩니까?
Aero Wang

151

$containsmongodb 에는 연산자 가 없습니다 .

JohnnyHK의 답변을 그대로 사용할 수 있습니다. 그 mongo가 포함하는 가장 가까운 유추는 $in이것을 사용하여 쿼리는 다음과 같습니다.

PersonModel.find({ favouriteFoods: { "$in" : ["sushi"]} }, ...);

10
이 올바른지? mongodb가 $ in을 사용할 때 값의 배열을 기대하지 않습니까? {name : {$ in : [ "Paul", "Dave", "Larry", "Adam"]}}?
Ludwig Magnusson

37
응? 이것은 불필요합니다. $in여러 쿼리 값이 있고 문서가 그 중 하나와 일치해야하는 경우에 사용됩니다. 반대로 (이 질문에 관한 것입니다) JohnnyHK의 대답은 맞습니다. 공감하려고했지만이 답변이이 페이지에 나오는 다른 사람들에게 도움이 될 것 같습니다.
MalcolmOcean

4
그러나 이것은 실제로 여러 값으로 쿼리하는 데 도움이되었습니다 .D 많은 감사합니다!
Alexandre Bourlier

10
감사. 이것이 실제로 내가 찾던 것, 여러 값을 검색하는 방법 :PersonModel.find({favouriteFoods: {"$in": ["sushi", "hotdog"]}})
totymedli

@MalcolmOcean은 $ in 연산자가 역 배열을 위해 배열을 으로 사용한다는 점에서 정확 합니다 . 필드 배열되는 질문에 대해 요구되는 것입니다. 그러나, 분야 및 값이 배열 인,이 대답하고 JohnnyHK 모두의 당신의 필요에 $을 의미, 관련입니다.
tscizzle

87

$all이 상황에서는 더 적절할 것 같습니다 . 스시에있는 사람을 찾고 있다면 :

PersonModel.find({ favoriteFood : { $all : ["sushi"] }, ...})

더 많은 검색을 필터링하려면 다음과 같이하십시오.

PersonModel.find({ favoriteFood : { $all : ["sushi", "bananas"] }, ...})

$inOR과 $allAND 와 같습니다. 이것을 확인하십시오 : https://docs.mongodb.com/manual/reference/operator/query/all/


죄송합니다. 이것은 내 질문에 대한 잘못된 답변입니다. 정확히 일치하는 것이 아니라 지정된 값이 포함 된 배열 만 찾습니다.
Ludwig Magnusson

17
이것은 귀하의 질문에 완벽하게 유효한 답변입니다! 하나의 값에 대해서는 $ all 또는 $ in 사용에 차이가 없습니다. "sushi", "bananas"와 같은 여러 값이있는 경우 $ all은 선호하는 음식 배열에 "sushi"및 "bananas"가있는 사람을 찾고 있습니다. $ in을 사용하면 "sushi"또는 "bananas가있는 사람이 있습니다. "가 가장 좋아하는 음식 배열입니다.
Jodo

예, $ contains는 없지만 $ all은 일종입니다
datdinhquoc

2
가장 좋은 답변입니다.
Nikolay Tsenkov

65

예를 들어 배열에 객체가 포함 된 경우 if favouriteFoods는 다음과 같은 객체의 배열입니다.

{
  name: 'Sushi',
  type: 'Japanese'
}

다음 쿼리를 사용할 수 있습니다.

PersonModel.find({"favouriteFoods.name": "Sushi"});

2
이것은 가장 좋은 대답입니다. 급할 때 사용하기가 훨씬 쉽습니다.
동네 짱 Schnoz

선택한 답변이어야합니다. MongoDB에서 중첩 문서 배열을 쿼리하는 경우 다음과 같이하십시오. 그것이 가장 효율적인지 확실하지 않지만 그것이 당신이하려는 모든 것이라면, 이것이 당신이 필요한 전부입니다.
Kyle L.

32

하위 문서 배열 내에서 NULL 요소가 포함 된 문서를 찾아야하는 경우이 쿼리는 꽤 잘 작동합니다.

db.collection.find({"keyWithArray":{$elemMatch:{"$in":[null], "$exists":true}}})

이 게시물은이 게시물에서 가져옵니다 : null 값을 가진 MongoDb 쿼리 배열

그것은 큰 발견이었고 내 자신의 초기 버전 과 잘못된 버전 보다 훨씬 잘 작동합니다 (하나의 요소가있는 배열에서만 잘 작동하는 것으로 나타났습니다).

.find({
    'MyArrayOfSubDocuments': { $not: { $size: 0 } },
    'MyArrayOfSubDocuments._id': { $exists: false }
})

3

find ()에 동의하는 것이 사용 사례에서 가장 효과적입니다. 여전히 많은 수의 항목에 대한 쿼리를 용이하게하고 특히 새 파일을 그룹화하고 작성하는 데 가치가있는 적은 수의 결과를 생성하기 위해 집계 프레임 워크에 $ match가 있습니다.

  PersonModel.aggregate([
            { 
                 "$match": { 
                     $and : [{ 'favouriteFoods' : { $exists: true, $in: [ 'sushi']}}, ........ ]  }
             },
             { $project : {"_id": 0, "name" : 1} }
            ]);

mongodb 4.2 ..와 함께 작동하지 않습니다. 답장을
보내

어떤 오류가 발생합니까? 자세히 제공하십시오.
Amitesh

3

lookup_food_array의 경우 배열입니다.

match_stage["favoriteFoods"] = {'$elemMatch': {'$in': lookup_food_array}}

lookup_food_array의 경우 문자열입니다.

match_stage["favoriteFoods"] = {'$elemMatch': lookup_food_string}

1

Loopback3의 경우 주어진 모든 예제가 나에게 적합하지 않거나 REST API를 사용하는 것만 큼 빠릅니다. 그러나 그것은 내가 필요한 정확한 답을 찾는 데 도움이되었습니다.

{"where":{"arrayAttribute":{ "all" :[String]}}}


1
당신은 생명의 은인입니다, 감사합니다! 그 문서는 어디에 있고 놓쳤습니까? 링크를 게시 할 수 있습니까? 감사.
user2078023

-3

javascript를 통해 "contains"연산자와 같은 것을 사용하려면 항상 정규 표현식을 사용할 수 있습니다.

예. 이름이 "Bartolomew"인 고객을 검색하려고한다고 가정하십시오.

async function getBartolomew() {
    const custStartWith_Bart = await Customers.find({name: /^Bart/ }); // Starts with Bart
    const custEndWith_lomew = await Customers.find({name: /lomew$/ }); // Ends with lomew
    const custContains_rtol = await Customers.find({name: /.*rtol.*/ }); // Contains rtol

    console.log(custStartWith_Bart);
    console.log(custEndWith_lomew);
    console.log(custContains_rtol);
}

-26

나는이 주제가 오래되었다는 것을 알고 있지만 동일한 질문을 궁금해 할 수있는 미래의 사람들에게는 또 다른 비효율적 인 해결책이있을 수 있습니다.

PersonModel.find({$where : 'this.favouriteFoods.indexOf("sushi") != -1'});

이것은 MongoDB에 의한 모든 최적화를 피하므로 프로덕션 코드에는 사용하지 마십시오.


호기심으로, 이런 식으로하는 이점이 있습니까?
Ludwig Magnusson

5
이것은 허용 된 답변과 비교할 때 매우 비효율적입니다. 그것은 몽고가 받아 들인 것처럼 똑바로 찾기 위해 뒤에서 넣은 모든 최적화를 우회합니다.
의식하지 못하는

1
이것은 내 경우에 필요한 답입니다! 감사합니다 "사용자":)
Vasyl Boroviak
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.