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는 여러 컬렉션 - 기간에 걸친 쿼리를 수행하지 않습니다.여러 컬렉션의 데이터를 조인해야 하는 경우 여러 쿼리를 수행하여 응용 프로그램 수준에서 조인해야 합니다.
- 쿼리 모음 A
- 결과에서 보조 키를 가져와 배열에 넣습니다.
- 해당 배열을 $in-operator의 값으로 전달하는 쿼리 컬렉션 B
- 응용 프로그램 계층에서 프로그래밍 방식으로 두 쿼리의 결과를 수행합니다.
이것을 해야만 하는 것은 보통이 아니라 오히려 예외가 되어야 합니다.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
'programing' 카테고리의 다른 글
이클립스 패키지 탐색기에서 열려 있는 파일을 표시하려면 어떻게 합니까? (0) | 2023.05.24 |
---|---|
문자열이 숫자인 경우 문자열을 int로 변환 (0) | 2023.05.24 |
MVVM 매드니스: 명령 (0) | 2023.05.24 |
NameError: 이름 'List'가 정의되지 않았습니다. (0) | 2023.05.24 |
움직이는 평균 판다 (0) | 2023.05.24 |