MongoDB: вывод «id» вместо «_id»

Я использую мангуст (узел), как лучше всего вывести идентификатор вместо _id?


person Johnny    schedule 12.08.2011    source источник
comment
Для новых читателей: ниже вы увидите несколько различных подходов. Целесообразно прочитать их все, прежде чем выбирать, вместо того, чтобы слепо идти за принятым или большинством голосов. Ваше здоровье!   -  person sshow    schedule 08.02.2018


Ответы (16)


Я создаю метод toClient() в своих моделях, где я это делаю. Это также хорошее место для переименования/удаления других атрибутов, которые вы не хотите отправлять клиенту:

Schema.method('toClient', function() {
    var obj = this.toObject();

    //Rename fields
    obj.id = obj._id;
    delete obj._id;

    return obj;
});
person evilcelery    schedule 12.08.2011
comment
Я действительно новичок в мангусте, это похоже на то, что я хочу. как вы называете это toClient? Обычно я делаю find() и возвращаю объект docs, а затем просто делаю res.send(docs). Итак, в этом случае я вызываю res.write(docs[1].toClient()) для каждого документа? Благодарность - person Johnny; 12.08.2011
comment
сейчас это не работает для меня - изменился ли способ сделать это в Mongoose? - person outside2344; 21.02.2013
comment
виртуальные, вероятно, то, что вы хотите. - person Leonidas; 20.03.2013

Учитывая, что вы используете Mongoose, вы можете использовать «виртуальные», которые по сути являются фальшивыми полями, которые создает Mongoose. Они не хранятся в БД, они просто заполняются во время выполнения:

// Duplicate the ID field.
Schema.virtual('id').get(function(){
    return this._id.toHexString();
});

// Ensure virtual fields are serialised.
Schema.set('toJSON', {
    virtuals: true
});

Каждый раз, когда toJSON вызывается для модели, которую вы создаете из этой схемы, она будет включать поле «id», которое соответствует полю _id, которое генерирует Mongo. Точно так же вы можете установить поведение для toObject таким же образом.

Видеть:

Вы можете абстрагировать это в BaseSchema, все ваши модели затем расширять/вызывать, чтобы сохранить логику в одном месте. Я написал это выше при создании приложения Ember/Node/Mongoose, поскольку Ember действительно предпочитает иметь поле «id» для работы.

person Pascal Zajac    schedule 27.12.2012
comment
Очень хорошее решение (+1). Я бы также добавил Schema.set('toObject', { virtuals: true }), чтобы иметь возможность видеть виртуальные выходные данные при использовании console.log(obj). - person Tom; 26.03.2014
comment
Это сохраняет поле _id. Вместо этого я предпочитаю решение для преобразования, которое мне предоставил shakinfree. - person Peter Hedberg; 12.04.2014
comment
'toJson' только при преобразовании в JSON. Более общий подход заключается в использовании toObject. mongoosejs.com/docs/guide.html#toObject - person Dave Jensen; 15.05.2014
comment
Я поместил его в модель, он не запускается, где его разместить? размещен под этим const companyCollection = mongoose.Schema({}); с помощью ExpressJs - person 151291; 16.01.2019
comment
В последней версии Mongoose (на данный момент 5.4.20) в API включен/предварительно встроен виртуальный геттер id. mongoosejs.com/docs/guide.html#id - person David Ferreira; 30.03.2019
comment
Я постоянно возвращаюсь к этому ответу :)) - person Developerium; 26.05.2020

Начиная с Mongoose v4.0 часть этой функциональности поддерживается по умолчанию. Больше не требуется вручную добавлять виртуальное поле id, как объяснил @Pascal Zajac.

Mongoose назначает каждой из ваших схем виртуальный геттер идентификатора по умолчанию, который возвращает поле _id документов, приведенное к строке, или, в случае ObjectIds, его hexString. Если вы не хотите, чтобы получатель идентификатора добавлялся в вашу схему, вы можете отключить его, передав эту опцию во время создания схемы. Источник

Однако для экспорта этого поля в формат JSON по-прежнему необходимо включить сериализацию виртуальных полей:

Schema.set('toJSON', {
    virtuals: true
});
person xaviert    schedule 22.12.2015
comment
Это было верно задолго до версии 4.0, но OP хочет, чтобы возвращался просто id (а не _id). Просто сказав мангусту включить виртуальный идентификатор, вы получите оба. - person neverfox; 03.01.2016
comment
Что делать, если у вас есть другие виртуальные машины, которые вы хотите исключить? - person Alex McMillan; 14.11.2018

Я использовал это:

schema.set('toJSON', {
  virtuals: true,
  versionKey:false,
  transform: function (doc, ret) {   delete ret._id  }
});

Я думаю, было бы здорово, если бы они автоматически подавляли _id, когда для виртуалов установлено значение true.

person Benamar    schedule 13.03.2017
comment
Этот работал на меня. Где схема — это каждая модель, которую вы создаете. Например: const UserSchema = new Schema({ stuff }); UserSchema.set("toJSON", { virtuals: true, versionKey: false, transform: function(doc, ret) { delete ret._id; } }); const User = model("user", UserSchema); - person user3152459; 15.03.2020
comment
Если кто-то сразу обнаружит, что это не работает, убедитесь, что вы не используете опцию lean: true при извлечении документов из базы данных. - person coatesap; 17.06.2020
comment
Управление версиями документа также можно отключить, установив для параметра versionKey значение false. НЕ отключайте управление версиями, если вы не знаете, что делаете. aaronheckmann.blogspot.com/2012/06/ mongoosejs.com/docs/guide.html#versionKey - person ET-CS; 10.07.2020

Вот альтернативная версия ответа, предоставленного пользователем @user3087827. Если вы обнаружите, что schema.options.toJSON не определено, вы можете использовать:

schema.set('toJSON', {
     transform: function (doc, ret, options) {
         ret.id = ret._id;
         delete ret._id;
         delete ret.__v;
     }
}); 
person Tom Makin    schedule 23.01.2014

//Transform
Schema.options.toJSON.transform = function (doc, ret, options) {
  // remove the _id of every document before returning the result
  ret.id = ret._id;
  delete ret._id;
  delete ret.__v;
}

есть свойство «Schema.options.toObject.transform», чтобы сделать обратное, или вы можете просто настроить его как виртуальный идентификатор.

person user3087827    schedule 10.12.2013

Если вы хотите использовать id вместо _id глобально, вы можете установить toJSON config для объекта mongoose(начиная с версии 5.3):

mongoose.set('toJSON', {
  virtuals: true,
  transform: (doc, converted) => {
    delete converted._id;
  }
});
person Murat Çorlu    schedule 13.04.2020
comment
Не работает !! мангуст 5.9.3 - person 151291; 11.06.2021

Для этой цели я создал простой в использовании плагин, который применяю ко всем мои проекты и все схемы по всему миру. Он преобразует _id в id, а также удаляет параметр __v.

Итак, он конвертирует:

{
  "_id": "400e8324a71d4410b9dc3980b5f8cdea",
  "__v": 2,
  "name": "Item A"
}

К более простому и чистому:

{
  "id": "400e8324a71d4410b9dc3980b5f8cdea",
  "name": "Item A"
}

Использование в качестве глобального плагина:

const mongoose = require('mongoose');
mongoose.plugin(require('meanie-mongoose-to-json'));

Или для конкретной схемы:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const MySchema = new Schema({});
MySchema.plugin(require('meanie-mongoose-to-json'));

Надеюсь, это поможет кому-то.

person Adam Reis    schedule 18.11.2016

Заменить метод по умолчанию toJSON новым:

schema.method('toJSON', function () {
   const { __v, _id, ...object } = this.toObject();
   object.id = _id;
   return object;
});
person Stan Fad    schedule 24.05.2019

Существует также normalize-mongoose простой пакет, который удаляет _id и __v за вас.

Из чего-то вроде этого:

import mongoose from 'mongoose';
import normalize from 'normalize-mongoose';

const personSchema = mongoose.Schema({ name: String });

personSchema.plugin(normalize);

const Person = mongoose.model('Person', personSchema);
const someone = new Person({ name: 'Abraham' });
const result = someone.toJSON();

console.log(result);

Итак, допустим, у вас есть что-то вроде этого:

{
  "_id": "5dff03d3218b91425b9d6fab",
  "name": "Abraham",
  "__v": 0
}

Вы получите этот вывод:

{
  "id": "5dff03d3218b91425b9d6fab",
  "name": "Abraham"
}
person abranhe    schedule 22.12.2019

Вы также можете использовать агрегатную функцию при поиске возвращаемых элементов. $project позволит вам создавать поля, которые вы можете сделать, и присвоить их _id.

<model>.aggregate([{$project: {_id: 0, id: '$_id'}], (err, res) => {
 // 
})
person user2062241    schedule 24.10.2017

Если вы используете lodash для выбора нужных элементов, это сработает для вас.

UserSchema.virtual('id').get(function(){
  return this._id.toHexString();
});

UserSchema.set('toObject', { virtuals: true })

UserSchema.methods.toJSON = function() {
  return _.pick( 
    this.toObject(), 
    ['id','email','firstName','lastName','username']
  );
person Ivor Scott    schedule 10.11.2018

Создайте базовую схему

import { Schema } from "mongoose";

    export class BaseSchema extends Schema {
        constructor(sche: any) {
            super(sche);
            this.set('toJSON', {
        virtuals: true,
        transform: (doc, converted) => {
            delete converted._id;
        }
    });
        }
    
    }

Теперь в вашей модели мангуста используйте BaseSchema вместо Schema

import mongoose, { Document} from 'mongoose';
import { BaseSchema } from '../../helpers/mongoose';

const UserSchema = new BaseSchema({
    name: String,
    age: Number,

});

export interface IUser {
    name: String,
    age: Number,

}

interface IPlanModel extends IUser, Document { }

export const PlanDoc = mongoose.model<IPlanModel>('User', UserSchema);

Реализация машинописного текста ответа @Pascal Zajac

person d-feverx    schedule 26.11.2020

Есть еще один драйвер, который делает это http://alexeypetrushin.github.com/mongo-lite set convertId вариант в истину. Дополнительные сведения см. в разделе «Значения по умолчанию и настройки».

person Alex Craft    schedule 10.05.2012

Переопределить toJSONmethod для конкретной схемы модели. https://mongoosejs.com/docs/api.html#schema_Schema-method

YourSchema.methods.toJSON = function () {
  return {
    id: this._id,
    some_field: this.some_field,
    created_at: this.createdAt
  }
}
person Sen Sokha    schedule 20.02.2020
comment
Не работает для мангуста версии 5.9.3 - person 151291; 11.06.2021

Вы также можете использовать предварительный хук «сохранить»:

TouSchema.pre('save', function () {      
  if (this.isNew) {
    this._doc.id = this._id;      
  } 
}
person Georgi Popov    schedule 07.02.2021