#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"
}
}
}
])