Как включить определенные поля из встроенного документа, не затрагивая родительский документ?

mongodb

#mongodb

Вопрос:

Как я могу включить определенные поля из встроенного документа, не затрагивая поля в родительском документе?

Из документации Mongo, расположенной здесь:

https://docs.mongodb.com/manual/reference/operator/aggregation/project/#include-specific-fields-from-embedded-documents

С вводом:

 [
  {
    _id: 1,
    user: "1234",
    stop: {
      title: "book1",
      author: "xyz",
      page: 32
    }
  },
  {
    _id: 2,
    user: "7890",
    stop: [
      {
        title: "book2",
        author: "abc",
        page: 5
      },
      {
        title: "book3",
        author: "ijk",
        page: 100
      }
    ]
  }
]
 

Вы можете выбрать только поле «заголовок» встроенного документа с помощью:

 db.bookmarks.aggregate( [ { $project: { stop: { title: 1 } } } ] )
 

Но это также исключает поле «пользователь» из родительского документа. Результаты:

 { "_id" : 1, "stop" : { "title" : "book1" } }
{ "_id" : 2, "stop" : [ { "title" : "book2" }, { "title" : "book3" } ] }
 

Обратите внимание, что я не знаю всех полей в родительском документе, поэтому я не могу их явно включить, и я не знаю всех полей во встроенном документе, поэтому я не могу их явно исключить.

Ответ №1:

Обновить

К сожалению, я не верю, что существует очень простой способ добиться этого, учитывая, что поля неизвестны.

Самое близкое, что я мог получить, это также включить весь документ в запрос, а затем удалить исходное поле «стоп». Это означает, что возвращаемые исходные данные корневого документа будут находиться в поле с именем «документ».

Я знаю, что это не совсем то, что вы ищете, но это настолько близко, насколько я мог получить.

Возможно, вы могли бы попытаться ввести $replaceRoot , чтобы этот новый реквизит «document» снова стал новым корнем?

Посмотрите живую демонстрацию здесь

База данных

 [
  {
    _id: 1,
    user: "1234",
    stop: {
      title: "book1",
      author: "xyz",
      page: 32
    }
  },
  {
    _id: 2,
    user: "7890",
    stop: [
      {
        title: "book2",
        author: "abc",
        page: 5
      },
      {
        title: "book3",
        author: "ijk",
        page: 100
      }
    ]
  }
]
 

Запрос

 db.collection.aggregate([
  {
    $project: {
      "stop.title": 1,
      document: "$ROOT",
      
    }
  },
  {
    $unset: [
      "document.stop"
    ]
  }
])
 

Результат

 [
  {
    "_id": 1,
    "document": {
      "_id": 1,
      "user": "1234"
    },
    "stop": {
      "title": "book1"
    }
  },
  {
    "_id": 2,
    "document": {
      "_id": 2,
      "user": "7890"
    },
    "stop": [
      {
        "title": "book2"
      },
      {
        "title": "book3"
      }
    ]
  }
]
 

Оригинал

Если я правильно понимаю, вам просто нужно спроецировать все stop поле.

Что-то вроде:

Запрос

 db.collection.aggregate([
  {
    $project: {
      stop: 1
    }
  }
])
 

Комментарии:

1. Спасибо за усилия, но это возвращает все поля из stop и по-прежнему удаляет поля из родительского. Я хочу, чтобы все поля были из родительского и только заголовок из stop.

2. ах, хорошо, это имеет больше смысла. дайте мне пару минут, и я обновлю свой ответ.

3. @JohnVottero пожалуйста, посмотрите мой обновленный ответ.