Programming

MongoDB 다 대다 협회

procodes 2020. 7. 6. 21:43
반응형

MongoDB 다 대다 협회


MongoDB와 다 대다 연결을 어떻게 수행 하시겠습니까?

예를 들어; Users 테이블과 Roles 테이블이 있다고 가정하겠습니다. 사용자에게는 많은 역할이 있으며 역할에는 많은 사용자가 있습니다. SQL 랜드에서는 UserRoles 테이블을 작성합니다.

Users:
    Id
    Name

Roles:
    Id
    Name

UserRoles:
    UserId
    RoleId

MongoDB에서 동일한 종류의 관계는 어떻게 처리됩니까?


쿼리 요구에 따라 모든 것을 사용자 문서에 넣을 수 있습니다.

{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 데이터 저장소를 사용하여 문서 저장소 솔루션을 모델링하는 것이 훨씬 쉽다는 것을 알게되었습니다. 쓰기 사용 사례에서 지원해야하는 쓰기 작업

예를 들어 "역할 사용자"도메인의 사용은 다음과 같습니다.

  1. 역할- "Is User In Role"(컨테이너 + 자체 메타 데이터와 같은 작업)을 지원하기 위해 작성, 읽기, 업데이트, 삭제, 사용자 나열, 사용자 추가, 사용자 제거, 모든 사용자 지우기, 사용자 색인 또는 이와 유사합니다.
  2. 사용자-작성, 읽기, 업데이트, 삭제 (자립 엔티티와 같은 CRUD 조작)

이것은 다음 문서 템플릿으로 모델링 할 수 있습니다.

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을 제거하기위한 많은 사용자 업데이트가 발생합니다. 그런 다음이 clear 작업은 일반적으로 권장되지 않지만 필요한 경우 작업을 주문하여 구현할 수 있습니다.

  1. Role.users에서 사용자 이름 목록을 가져옵니다.
  2. 1 단계에서 사용자 이름을 반복하고 User.roles에서 역할 이름을 제거하십시오.
  3. Role.users를 지우십시오.

In the case of an issue, which is most likely to occur within step 2, a rollback is easy as the same set of user names from step 1 can be used to recover or continue.


I've just stumbled upon this question and, although it's an old one, I thought it would be useful to add a couple of possibilities not mentioned in the answers given. Also, things have moved on a bit in the last few years, so it is worth emphasising that SQL and NoSQL are moving closer to each other.

One of the commenters brought up the wise cautionary attitude that “if data is relational, use relational”. However, that comment only makes sense in the relational world, where schemas always come before the application.

RELATIONAL WORLD: Structure data > Write application to get it
NOSQL WORLD: Design application > Structure data accordingly

Even if data is relational, NoSQL is still an option. For example, one-to-many relationships are no problem at all and are widely covered in MongoDB docs

A 2015 SOLUTION TO A 2010 PROBLEM

Since this question was posted, there have been serious attempts at bringing noSQL closer to SQL. The team led by Yannis Papakonstantinou at the University of California (San Diego) have been working on FORWARD, an implementation of SQL++ which could soon be the solution to persistent problems like the one posted here.

At a more practical level, the release of Couchbase 4.0 has meant that, for the first time, you can do native JOINs in NoSQL. They use their own N1QL. This is an example of a JOIN from their tutorials:

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 allows for most if not all SQL operations including aggregration, filtering, etc.

THE NOT-SO-NEW HYBRID SOLUTION

If MongoDB is still the only option, then I'd like to go back to my point that the application should take precedence over the structure of data. None of the answers mention hybrid embedding, whereby most queried data is embedded in the document/object, and references are kept for a minority of cases.

Example: can information (other than role name) wait? could bootstrapping the application be faster by not requesting anything that the user doesn't need yet?

This could be the case if user logs in and s/he needs to see all the options for all the roles s/he belongs to. However, the user is an “Engineer” and options for this role are rarely used. This means the application only needs to show the options for an engineer in case s/he wants to click on them.

This can be achieved with a document which tells the application at the start (1) which roles the user belongs to and (2) where to get information about an event linked to a particular role.

   {_id: ObjectID(),
    roles: [[“Engineer”, “ObjectId()”],
            [“Administrator”, “ObjectId()”]]
   }

Or, even better, index the role.name field in the roles collection, and you may not need to embed ObjectID() either.

Another example: is information about ALL the roles requested ALL the time?

It could also be the case that the user logs in to the dashboard and 90% of the time performs tasks linked to the “Engineer” role. Hybrid embedding could be done for that particular role in full and keep references for the rest only.

{_id: ObjectID(),
  roles: [{name: “Engineer”, 
           property1: value1,
           property2: value2
          },   
          [“Administrator”, “ObjectId()”]
         ]
}

Being schemaless is not just a characteristic of NoSQL, it could be an advantage in this case. It's perfectly valid to nest different types of objects in the “Roles” property of an user object.


in case when employee and company is entity-object try to use following schema:

employee{
   //put your contract to employee
   contracts:{ item1, item2, item3,...}
}

company{
   //and duplicate it in company
   contracts:{ item1, item2, item3,...}
}

참고URL : https://stackoverflow.com/questions/2336700/mongodb-many-to-many-association

반응형