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


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.