Как использовать полнотекстовый поиск в ссылочных документах?

#mongodb #mongodb-query

#mongodb #mongodb-запрос

Вопрос:

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

У меня есть несколько документов, в которых есть ссылка на другой документ, например users , и orders :

Users Модель:

 import mongoose from '../database/index.js';
import mongoosePaginate from 'mongoose-paginate-v2';

const UsersSchema = new mongoose.Schema({
    user_id: {
        type: String,
        required: true,
    },
    email: {
        type: String,
        required: true,
        unique: true,
    },
    firstName: {
        type: String,
        default: '',
    },
    lastName: {
        type: String,
        default: '',
    },
    orders: [
        {
            type: mongoose.Schema.Types.ObjectId,
            ref: 'Orders',
        },
    ],
    recipients: [
        {
            type: mongoose.Schema.Types.ObjectId,
            ref: 'Recipients',
        },
    ],
    createdAt: {
        type: Date,
        default: Date.now,
        required: true,
        select: false,
    },
});

UsersSchema.index({ email: 'text', firstName: 'text', lastName: 'text' });

UsersSchema.plugin(mongoosePaginate);

UsersSchema.set('toJSON', {
    virtuals: true,
});

const Users = mongoose.model('Users', UsersSchema);

export default Users;
  

Orders Модель:

 import mongoose from '../database/index.js';
import mongoosePaginate from 'mongoose-paginate-v2';
import Users from './users.js';

import OrderStatus from '../enums/OrderStatusEnum.js';

const OrdersSchema = new mongoose.Schema({
    user: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Users',
        required: true,
    },
    total: {
        type: Number,
        required: true,
    },
    status: {
        type: String,
        enum: OrderStatus.values(),
        required: true,
        default: OrderStatus.CREATED,
    },
    payment: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'PaymentMethods',
        required: true,
    },
    shortId: {
        type: String,
        required: true,
    },
    createdAt: {
        type: Date,
        default: Date.now,
        required: true,
    },
});

OrdersSchema.index({ shortId: 'text' });

OrdersSchema.plugin(mongoosePaginate);

OrdersSchema.pre('remove', function (next) {
    Users.update({ orders: this._id }, { $pull: { orders: this._id } }).exec();
    next();
});

OrdersSchema.set('toJSON', {
    virtuals: true,
});

const Orders = mongoose.model('Orders', OrdersSchema);

export default Orders;
  

Я могу использовать $text поиск для запроса полнотекстового поиска по заказам или пользователям:

     const orders = await Orders.paginate(
        { $text: { $search: query.filter.q } },
        query.options
    );
    return orders;
  

Но это приведет только к поиску по индексу заказов. Если, например, я хотел бы выполнить поиск по порядку имени пользователя Joe , как я могу сделать так, чтобы он также выполнял поиск в user.firstName поле, поскольку это ссылка от Orders до Users ?

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

Заранее спасибо

Ответ №1:

Поскольку полнотекстовый поисковый запрос должен быть первым этапом конвейера агрегации, в настоящее время невозможно выполнить полнотекстовый поиск в двух коллекциях как часть одного и того же запроса.

Вам нужно будет реорганизовать свои данные.

Ответ №2:

моим требованием было найти заказы пользователей, соответствующие их именам, частичный или полнотекстовый поиск. идентификатор пользователя указан в документе orders.

с игровой площадки mongodb: https://mongoplayground.net/p/ASOSFvfURXW

 db.inventory.aggregate([
  {
    "$lookup": {
      "from": "orders",
      "localField": "orderId",
      "foreignField": "_id",
      "as": "order_docs"
    }
  },
  {
    "$unwind": "$order_docs"
  },
  {
    "$match": {
      "order_docs.item": {
        "$regex": "pec",
        "$options": "i"
      }
    }
  }
])