Automattic / mongoose

MongoDB object modeling designed to work in an asynchronous environment.
https://mongoosejs.com
MIT License
26.97k stars 3.84k forks source link

Is there some function that helps to search for the populated property? #11294

Closed cheezone closed 2 years ago

cheezone commented 2 years ago

Do you want to request a feature or report a bug?

feature

What is the current behavior?

None

If the current behavior is a bug, please provide the steps to reproduce.

None

What is the expected behavior?

My models:

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
@Schema()
export class Application {
  @Prop()
  name: string;
}
export const ApplicationSchema = SchemaFactory.createForClass(
  Application,
)
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Types } from 'mongoose';
import { Application } from 'src/core/applications/entities/application.entity';

@Schema({ toJSON: { getters: true } })
export class Manufacturer extends Thing { 

  @Prop({
    type: [{ autopopulate: true, type: Types.ObjectId, ref: 'Application' }],
  })
  applications: Application[];
}

export const ManufacturerSchema = SchemaFactory.createForClass(Manufacturer);

  search(
    keyword: string,
    columns: string[] = ['name'],
    select: FilterQuery<T> = {},
    projection: any | null = null,
    options: QueryOptions | null = null,
  ): Promise<HydratedDocument<T, TMethods, TVirtuals>[] | null> {
    const regex = new RegExp(keyword, 'i');
    const $or = columns.map(
      (name) => { [name]: regex },
    );
    const result = (async () => {
      // extract the path whose type is ObjectId...
      const result = await this.model
        .find({ $and: [{ $or }, select] }, projection, options)
        .exec();
        // do something...
      return result;
    })();
    return result;
  }

I want a search function that can search the Manufacturer's applications's properties.

But when I using find function of Model to deal with the columns like applications.$.name, the data has not been populated.

So I want to ask, is there a function that can extract the path whose type is ref ObjectId? That way, I can separate them out of columns and normal columns before finding them.

I also need a function that can search in the result array, it needs to support the dot operator etc. Mongoose features. I don't want to build another wheel myself......

e.g.

const columns = ['name','applications.$.name']
const refColumns = this.model.schema.doSomeThingWith(columns) // ['applications.$.name']
const findColumns = _.difference(columns, refPaths) // ['name']

const findResult = await this.model.find(...).exec() // find use findColumns

const result = this.model.doSomeThingWith(findResult, { $or : refColumns.map(name)=({ [name]: regex })}) // filter with 'applications.$.name'

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.

Mongoose : 6.1.8 Node.js : 16.13.2

vkarpov15 commented 2 years ago

No, there isn't. You would either need to use $lookup, or make applicationNames a property of Manufacturer