programing

Mongodb String에서 ObjectId로 _id 필드에 가입

bestprogram 2023. 5. 17. 23:32

Mongodb String에서 ObjectId로 _id 필드에 가입

저는 두 개의 컬렉션을 가지고 있습니다.

  1. 사용자

    {
       "_id" : ObjectId("584aac38686860d502929b8b"),
       "name" : "John"
    }
    
  2. 역할.

    {
       "_id" : ObjectId("584aaca6686860d502929b8d"),
       "role" : "Admin",
       "userId" : "584aac38686860d502929b8b"  
    }
    

userId(역할 컬렉션) - _id(사용자 컬렉션)를 기준으로 이러한 컬렉션에 참여하고 싶습니다.

다음 질문을 시도했습니다.

db.role.aggregate({
  "$lookup": {
    "from": "user",
    "localField": "userId",
    "foreignField": "_id",
    "as": "output"
  }
})

이것은 userId를 ObjectId로 저장하는 한 예상 결과를 제공합니다.userId가 문자열인 경우 결과가 없습니다.Ps: 노력했습니다.

외부 필드: '_id'.valueOf()

그리고.

외부 필드: '_id'.toString()

그러나 ObjectId 문자열 필드를 기준으로 일치/가입할 수 없습니다.

어떤 도움이든 감사하겠습니다.

문자열을 변환하는 mongodb 4.0의 집계를 사용할 수 있습니다.id로.ObjectId

db.role.aggregate([
  { "$lookup": {
    "from": "user",
    "let": { "userId": "$_id" },
    "pipeline": [
      { "$addFields": { "userId": { "$toObjectId": "$userId" }}},
      { "$match": { "$expr": { "$eq": [ "$userId", "$$userId" ] } } }
    ],
    "as": "output"
  }}
])

또는 mongodb 4.0의 집계를 사용하여 다음을 변환할 수 있습니다.ObjectId로.String

db.role.aggregate([
  { "$addFields": { "userId": { "$toString": "$_id" }}},
  { "$lookup": {
    "from": "user",
    "localField": "userId",
    "foreignField": "userId",
    "as": "output"
  }}
])

이것은 MongoDB 3.4 이후에는 불가능합니다.이 기능은 이미 요청되었지만 아직 구현되지 않았습니다.해당 티켓은 다음과 같습니다.

지금은 userId를 ObjectId로 저장해야 합니다.


편집

이전 티켓은 MongoDB 4.0에서 고정되었습니다.이제 다음 쿼리를 사용하여 이를 달성할 수 있습니다.

db.user.aggregate([
  {
    "$project": {
      "_id": {
        "$toString": "$_id"
      }
    }
  },
  {
    "$lookup": {
      "from": "role",
      "localField": "_id",
      "foreignField": "userId",
      "as": "role"
    }
  }
])

결과:

[
  {
    "_id": "584aac38686860d502929b8b",
    "role": [
      {
        "_id": ObjectId("584aaca6686860d502929b8d"),
        "role": "Admin",
        "userId": "584aac38686860d502929b8b"
      }
    ]
  }
]

온라인으로 시도해 보십시오: mongoplayground.net/p/JoLPVIb1OLS

이전 답변에 오류가 있는 것 같습니다.$toObjectId케이스. 그let문은 함수가 있는 DB 컬렉션에 적용됩니다.aggregate는 "from"(즉, 'user')가 가리키는 컬렉션에서가 아니라 (즉, '역할')이라고 부릅니다.

db.role.aggregate([
  { "$lookup": {
    "let": { "userObjId": { "$toObjectId": "$userId" } },
    "from": "user",
    "pipeline": [
      { "$match": { "$expr": { "$eq": [ "$_id", "$$userObjId" ] } } }
    ],
    "as": "userDetails"
  }}
])

또는

db.role.aggregate([
  { "$project": { "userObjId": { "$toObjectId": "$userId" } } },
  { "$lookup": {
    "localField": "userObjId",
    "from": "user",
    "foreignField": "$_id",
    "as": "userDetails"
  }}
])

그리고.

db.user.aggregate([
  { "$project": { "userStrId": { "$toString": "$_id" }}},
  { "$lookup": {
    "localField": "userStrId",
    "from": "role",
    "foreignField": "userId",
    "as": "roleDetails"
  }}
])

예를 들어 두 가지 컬렉션이 있습니다.

  • {'_id'와 같은 작성자: ObjectId(), 이름: 'John Smith'}
  • {'_id'와 같은 메시지: ObjectId(), 텍스트: '메시지 텍스트', 작성자ID: 'stringId'}
  • 그리고 작성자 이름과 다른 데이터가 포함된 메시지를 받아야 합니다.

그러면:

db.messages.aggregate([
  {
    $addFields: {
      '$authorObjectId': {$toObjectId: $authorId}  
    }
  },
  {
    $lookup: {
      from: 'authors',
      localField: '$authorObjectId',
      foreignField: '_id',
      as: 'author'
    }
  }
 ])

설명:

NAT의 집계 파이프라인은 두 단계로 구성됩니다.

  • 첫 번째: ObjectId()로 변환된 문자열 authorId가 포함된 메시지에 필드를 추가합니다.
  • 둘째: 우리는 이 필드를 외부 필드 '_id'(작성자)와 비교하기 위해 localField(메시지)로 사용합니다.

언급URL : https://stackoverflow.com/questions/41093647/mongodb-join-on-id-field-from-string-to-objectid