programing

MongoDB에서 여러 컬렉션 검색

oldcodes 2023. 5. 24. 22:21
반응형

MongoDB에서 여러 컬렉션 검색

저는 MongoDB의 이론과 조인을 지원하지 않는다는 사실을 알고 있으며, 내장된 문서를 사용하거나 가능한 한 정규화를 해제해야 한다는 사실을 알고 있지만, 다음과 같습니다.

다음과 같은 여러 문서가 있습니다.

  • 교외를 포함하지만 이름, 성도 포함하는 사용자
  • 주를 포함하는 교외 지역
  • 학교를 포함하는 하위 항목은 사용자에 속하지만 이름, 성도 있습니다.

예:

Users:
{ _id: 1, first_name: 'Bill', last_name: 'Gates', suburb: 1 }
{ _id: 2, first_name: 'Steve', last_name: 'Jobs', suburb: 3 }

Suburb:
{ _id: 1, name: 'Suburb A', state: 1 }
{ _id: 2, name: 'Suburb B', state: 1 }
{ _id: 3, name: 'Suburb C', state: 3 }

State:
{ _id: 1, name: 'LA' }
{ _id: 3, name: 'NY' }

Child:
{ _id: 1, _user_id: 1, first_name: 'Little Billy', last_name: 'Gates' }
{ _id: 2, _user_id: 2, first_name: 'Little Stevie', last_name: 'Jobs' }

구현해야 하는 검색은 다음과 같습니다.

  • 이름, 사용자 및 하위 이름
  • 사용자 상태

이 작업을 수행하려면 여러 개의 쿼리를 수행해야 한다는 것을 알고 있습니다. 하지만 어떻게 수행할 수 있습니까?mapReduce 또는 aggregate 중 어느 것으로 하시겠습니까?

해결책을 지적해 주시겠습니까?

저는 mapReduce를 사용하려고 했지만, 그것은 사용자들로부터 state_id가 포함된 문서를 받지 못했기 때문에 그것을 여기로 가져왔습니다.

이 대답은 구식입니다.버전 3.2 이후, MongoDB는 $lookup 집계 연산자와의 왼쪽 외부 조인을 제한적으로 지원합니다.

MongoDB는 여러 컬렉션 - 기간에 걸친 쿼리를 수행하지 않습니다.여러 컬렉션의 데이터를 조인해야 하는 경우 여러 쿼리를 수행하여 응용 프로그램 수준에서 조인해야 합니다.

  1. 쿼리 모음 A
  2. 결과에서 보조 키를 가져와 배열에 넣습니다.
  3. 해당 배열을 $in-operator의 값으로 전달하는 쿼리 컬렉션 B
  4. 응용 프로그램 계층에서 프로그래밍 방식으로 두 쿼리의 결과를 수행합니다.

이것을 해야만 하는 것은 보통이 아니라 오히려 예외가 되어야 합니다.JOIN을 자주 에뮬레이트해야 하는 경우 데이터베이스 스키마를 설계할 때 여전히 너무 관계적으로 생각하거나 데이터가 MongoDB의 문서 기반 스토리지 개념에 적합하지 않다는 것을 의미합니다.

이제 mongodb에서 가입이 가능하며 여기서 사용 및 집계를 수행할 수 있으며 여러 컬렉션에서 찾을 수 있는 가장 좋은 방법은 무엇입니까?

db.collection.aggregate([
  { "$limit": 1 },
  { "$facet": {
    "c1": [
      { "$lookup": {
        "from": Users.collection.name,
        "pipeline": [
          { "$match": { "first_name": "your_search_data" } }
        ],
        "as": "collection1"
      }}
    ],
    "c2": [
      { "$lookup": {
        "from": State.collection.name,
        "pipeline": [
          { "$match": { "name": "your_search_data" } }
        ],
        "as": "collection2"
      }}
    ],
    "c3": [
      { "$lookup": {
        "from": State.collection.name,
        "pipeline": [
          { "$match": { "name": "your_search_data" } }
        ],
        "as": "collection3"
      }}
    ]
  }},
  { "$project": {
    "data": {
      "$concatArrays": [ "$c1", "$c2", "$c3" ]
    }
  }},
  { "$unwind": "$data" },
  { "$replaceRoot": { "newRoot": "$data" } }
])

스키마 설계에 대해 비정규화된 접근 방식을 취하면 MongoDB를 더 쉽게 이해할 수 있습니다.즉, 요청 클라이언트 응용프로그램이 문서를 이해하는 방식으로 문서를 구성하려고 합니다.기본적으로 사용자는 문서를 응용프로그램이 처리하는 도메인 개체로 모델링합니다.이러한 방식으로 데이터를 모델링할 때 조인의 중요성이 줄어듭니다.데이터를 단일 컬렉션으로 비정규화한 방법을 고려해 보십시오.

{  
    _id: 1, 
    first_name: 'Bill', 
    last_name: 'Gates', 
    suburb: 'Suburb A',
    state: 'LA',
    child : [ 3 ]
}

{ 
    _id: 2, 
    first_name: 'Steve', 
    last_name: 'Jobs', 
    suburb: 'Suburb C',
    state 'NY',
    child: [ 4 ] 
}
{ 
    _id: 3, 
    first_name: 'Little Billy', 
    last_name: 'Gates',
    suburb: 'Suburb A',
    state: 'LA',
    parent : [ 1 ]
}

{
    _id: 4, 
    first_name: 'Little Stevie', 
    last_name: 'Jobs'
    suburb: 'Suburb C',
    state 'NY',
    parent: [ 2 ]
}

첫 번째 장점은 이 스키마를 쿼리하기가 훨씬 쉽다는 것입니다.또한 주소 필드는 단일 문서에 포함되어 있으므로, 주소 필드에 대한 업데이트는 개별 사용자 엔터티와 일치합니다.부모와 자녀 사이의 양방향 관계도 주목하십니까?이것은 이 컬렉션을 단순히 개별 사람들의 컬렉션 이상으로 만듭니다.부모-자녀 관계는 이 컬렉션도 소셜 그래프임을 의미합니다.다음은 MongoDB에서 스키마 설계를 생각할 때 도움이 될 수 있는 몇 가지 리소스입니다.

다음은 지정된 기준과 일치하는 모든 레코드 배열을 반환하고 현재 데이터베이스의 모든 컬렉션을 검색하는 JavaScript 함수입니다.

function searchAll(query,fields,sort) {
    var all = db.getCollectionNames();
    var results = [];
    for (var i in all) {
        var coll = all[i];
        if (coll == "system.indexes") continue;
        db[coll].find(query,fields).sort(sort).forEach(
            function (rec) {results.push(rec);} );
    }
    return results;
}

Mongo 셸에서 함수를 복사/붙여넣은 다음과 같이 호출할 수 있습니다.

> varrecs = searchAll ({details: {$regex:.pdf$'}), {moddate:1,debug:1,_id:0, {debug:1}) > recs

@brian-moquin 등을 기반으로 간단한 키워드로 전체 키(필드)로 전체 컬렉션을 검색하는 기능을 만들었습니다.

그것은 제 요지에 있습니다; https://gist.github.com/fkiller/005dc8a07eaa3321110b3e5753dda71b

자세한 내용은 먼저 모든 키를 모으는 기능을 만들었습니다.

function keys(collectionName) {
    mr = db.runCommand({
        'mapreduce': collectionName,
        'map': function () {
            for (var key in this) { emit(key, null); }
        },
        'reduce': function (key, stuff) { return null; },
        'out': 'my_collection' + '_keys'
    });
    return db[mr.result].distinct('_id');
}

그러면 생성할 하나 더$or키 배열에서 쿼리합니다.

function createOR(fieldNames, keyword) {
    var query = [];
    fieldNames.forEach(function (item) {
        var temp = {};
        temp[item] = { $regex: '.*' + keyword + '.*' };
        query.push(temp);
    });
    if (query.length == 0) return false;
    return { $or: query };
}

아래는 단일 컬렉션을 검색하는 기능입니다.

function findany(collection, keyword) {
    var query = createOR(keys(collection.getName()));
    if (query) {
        return collection.findOne(query, keyword);
    } else {
        return false;
    }
}

마지막으로 모든 컬렉션에 대한 검색 기능을 제공합니다.

function searchAll(keyword) {
    var all = db.getCollectionNames();
    var results = [];
    all.forEach(function (collectionName) {
        print(collectionName);
        if (db[collectionName]) results.push(findany(db[collectionName], keyword));
    });
    return results;
}

Mongo 콘솔에서 모든 기능을 로드하고 실행할 수 있습니다.searchAll('any keyword')

MongoDB 드라이버에 의한 $mergeObjects를 사용하여 이를 달성할 수 있습니다. 예 다음 문서를 사용하여 수집 주문 생성:

db.orders.insert([
  { "_id" : 1, "item" : "abc", "price" : 12, "ordered" : 2 },
  { "_id" : 2, "item" : "jkl", "price" : 20, "ordered" : 1 }
])

다음 문서를 사용하여 다른 컬렉션 항목을 만듭니다.

db.items.insert([
  { "_id" : 1, "item" : "abc", description: "product 1", "instock" : 120 },
  { "_id" : 2, "item" : "def", description: "product 2", "instock" : 80 },
  { "_id" : 3, "item" : "jkl", description: "product 3", "instock" : 60 }
])

다음 작업은 먼저 $lookup 단계를 사용하여 항목 필드별로 두 컬렉션을 결합한 다음 $replaceRoot의 $mergeObjects를 사용하여 결합된 문서를 항목 및 주문에서 병합합니다.

db.orders.aggregate([
   {
      $lookup: {
         from: "items",
         localField: "item",    // field in the orders collection
         foreignField: "item",  // field in the items collection
         as: "fromItems"
      }
   },
   {
      $replaceRoot: { newRoot: { $mergeObjects: [ { $arrayElemAt: [ "$fromItems", 0 ] }, "$$ROOT" ] } }
   },
   { $project: { fromItems: 0 } }
])

이 작업은 다음 문서를 반환합니다.

{ "_id" : 1, "item" : "abc", "description" : "product 1", "instock" : 120, "price" : 12, "ordered" : 2 }
{ "_id" : 2, "item" : "jkl", "description" : "product 3", "instock" : 60, "price" : 20, "ordered" : 1 }

이 매개 변수는 개체를 병합하고 결과를 반환합니다.

수정이 필요하다는 점을 제외하고 미니멈 솔루션이 작동했습니다. var query =OR(key(collection.getName()); 생성하려면 키워드를 두 번째 매개 변수로 추가해야 합니다.아니면 여기로 전화하세요.

언급URL : https://stackoverflow.com/questions/20056903/search-on-multiple-collections-in-mongodb

반응형