답변:
쿼리 요구에 따라 모든 것을 사용자 문서에 넣을 수 있습니다.
{name:"Joe"
,roles:["Admin","User","Engineer"]
}
모든 엔지니어를 얻으려면 다음을 사용하십시오.
db.things.find( { roles : "Engineer" } );
별도의 문서에서 역할을 유지하려면 이름 대신 문서의 _id를 역할 배열에 포함시킬 수 있습니다.
{name:"Joe"
,roles:["4b5783300334000000000aa9","5783300334000000000aa943","6c6793300334001000000006"]
}
다음과 같은 역할을 설정하십시오.
{_id:"6c6793300334001000000006"
,rolename:"Engineer"
}
RDBMS에 대한 수년간의 경험에 따라 모델링을 시도하는 대신 원자력을 고려하면서 읽기 사용 사례를 최적화하여 MongoDB, Redis 및 기타 NoSQL 데이터 저장소를 사용하여 문서 저장소 솔루션을 모델링하는 것이 훨씬 쉽다는 것을 알았습니다. 쓰기 사용 사례에서 지원해야하는 쓰기 작업
예를 들어 "역할 사용자"도메인의 사용은 다음과 같습니다.
이것은 다음 문서 템플릿으로 모델링 할 수 있습니다.
User: { _id: UniqueId, name: string, roles: string[] }
Indexes: unique: [ name ]
Role: { _id: UniqueId, name: string, users: string[] }
Indexes: unique: [ name ]
User 엔터티의 역할 관련 기능과 같은 높은 빈도의 사용을 지원하기 위해 User.Roles는 의도적으로 비정규 화되어 중복 저장소가있는 Role.Users 및 User에 저장됩니다.
텍스트에서 쉽게 알 수 없지만 문서 리포지토리를 사용할 때 권장되는 유형의 사고입니다.
이것이 작업의 읽기 측면과 관련된 격차를 해소하는 데 도움이되기를 바랍니다.
쓰기 측면에서 권장되는 것은 원자 쓰기에 따라 모델링하는 것입니다. 예를 들어, 문서 구조가 잠금 획득, 한 문서, 다른 문서 및 가능하면 더 많은 문서를 업데이트 한 다음 잠금을 해제해야하는 경우 모델이 실패했을 수 있습니다. 분산 잠금을 구축 할 수 있다고해서 반드시 사용하도록되어있는 것은 아닙니다.
User in Roles 모델의 경우, 잠금의 원자 적 쓰기 방지를 확장하는 작업은 역할에서 사용자를 추가하거나 제거하는 것입니다. 두 경우 모두 성공적인 작업으로 인해 단일 사용자 및 단일 역할 문서가 모두 업데이트됩니다. 문제가 발생하면 정리하기가 쉽습니다. 이것이 문서 저장소가 사용되는 작업 단위 패턴이 많이 나타나는 이유 중 하나입니다.
원자 적 쓰기 방지 잠금을 실제로 확장하는 작업으로 인해 역할이 지워져 User.roles 배열에서 Role.name을 제거하기위한 많은 사용자 업데이트가 발생합니다. 이 클리어 작업은 일반적으로 권장되지 않지만 필요한 경우 작업을 주문하여 구현할 수 있습니다.
2 단계에서 발생할 가능성이 가장 높은 문제의 경우 1 단계와 동일한 사용자 이름 세트를 사용하여 복구하거나 계속할 수 있으므로 롤백이 쉽습니다.
방금이 질문에 걸려 넘어졌지만 오래된 질문이지만 주어진 답변에 언급되지 않은 몇 가지 가능성을 추가하는 것이 유용 할 것이라고 생각했습니다. 또한 지난 몇 년 동안 상황이 조금 바뀌 었으므로 SQL과 NoSQL이 서로 더 가까워지고 있음을 강조하는 것이 좋습니다.
주석가 중 한 명이“데이터가 관계형 인 경우 관계형을 사용하십시오”라는 현명한주의 태도를 나타 냈습니다. 그러나이 주석은 관계형 세계에서만 의미가 있으며 스키마는 항상 응용 프로그램보다 우선합니다.
관계 세계 : 구조 데이터>이를 얻기 위해 응용 프로그램 작성
NOSQL 세계 : 설계 응용 프로그램> 그에 따라 구조 데이터
데이터가 관계형이더라도 NoSQL은 여전히 옵션입니다. 예를 들어 일대 다 관계는 전혀 문제가되지 않으며 MongoDB 문서 에서 광범위하게 다루고 있습니다.
이 질문이 게시 된 이후, noSQL을 SQL에 더 가까이 가져 오려는 심각한 시도가있었습니다. 캘리포니아 대학 (샌디에고)의 Yannis Papakonstantinou가 이끄는 팀은 FORWARD 를 개발하고 있으며, 여기에 게시 된 것과 같은 지속적인 문제에 대한 해결책이 될 수있는 SQL ++을 구현했습니다.
보다 실질적인 수준에서 Couchbase 4.0 릴리스는 NoSQL에서 처음으로 네이티브 JOIN을 수행 할 수 있음을 의미했습니다. 그들은 자신의 N1QL을 사용합니다. 이것은의 예입니다 JOIN
그들의에서 자습서 :
SELECT usr.personal_details, orders
FROM users_with_orders usr
USE KEYS "Elinor_33313792"
JOIN orders_with_users orders
ON KEYS ARRAY s.order_id FOR s IN usr.shipped_order_history END
N1QL은 집계, 필터링 등을 포함한 모든 SQL 작업을 허용하지는 않습니다.
MongoDB가 여전히 유일한 옵션이라면 응용 프로그램이 데이터 구조보다 우선해야한다는 점으로 돌아가고 싶습니다. 대부분의 쿼리 된 데이터가 문서 / 객체에 임베드되어 소수의 경우에 대한 참조가 유지되는 하이브리드 임베딩에 대한 답변은 없습니다.
예 : 역할 이름 이외의 정보가 기다릴 수 있습니까? 사용자가 아직 필요하지 않은 것을 요청하지 않으면 응용 프로그램을 부트 스트랩하는 것이 더 빠를 수 있습니까?
사용자가 로그인하여 자신이 속한 모든 역할에 대한 모든 옵션을 확인해야하는 경우가 이에 해당합니다. 그러나 사용자는 "엔지니어"이며이 역할에 대한 옵션은 거의 사용되지 않습니다. 이는 엔지니어가 엔지니어를 클릭하려는 경우 애플리케이션에 대한 옵션 만 표시하면됨을 의미합니다.
이는 시작시 응용 프로그램에 사용자에게 속한 역할과 (2) 특정 역할에 연결된 이벤트에 대한 정보를 얻을 수있는 위치를 알려주는 문서를 통해 달성 할 수 있습니다.
{_id: ObjectID(),
roles: [[“Engineer”, “ObjectId()”],
[“Administrator”, “ObjectId()”]]
}
또는 역할 컬렉션에서 role.name 필드를 색인화하면 ObjectID ()를 포함하지 않아도됩니다.
다른 예 : 항상 요청 된 모든 역할에 대한 정보입니까?
사용자가 대시 보드에 로그인하고 90 %의 시간이 "엔지니어"역할과 연결된 작업을 수행하는 경우도 있습니다. 특정 역할에 대해 하이브리드 임베딩을 완전히 수행하고 나머지 부분에 대해서만 참조를 유지할 수 있습니다.
{_id: ObjectID(),
roles: [{name: “Engineer”,
property1: value1,
property2: value2
},
[“Administrator”, “ObjectId()”]
]
}
스키마가없는 것은 NoSQL의 특성 일뿐만 아니라이 경우 이점이 될 수 있습니다. 사용자 객체의 "역할"속성에 다른 유형의 객체를 중첩하는 것은 완벽하게 유효합니다.
직원과 회사가 엔티티 오브젝트 인 경우 다음 스키마를 사용하십시오.
employee{
//put your contract to employee
contracts:{ item1, item2, item3,...}
}
company{
//and duplicate it in company
contracts:{ item1, item2, item3,...}
}