带有全文搜索和项目的 Mongoose 子字段聚合
Posted
技术标签:
【中文标题】带有全文搜索和项目的 Mongoose 子字段聚合【英文标题】:Mongoose sub field aggregation with full text search and project 【发布时间】:2018-03-29 11:11:21 【问题描述】:我有一个名为 Session 的 Mongoose 模型,其中有一个名为 course 的字段(Course 模型),我想要使用全文搜索对 sessions 执行全文搜索,我还想使用 course 子字段中的字段聚合结果并选择一些字段,例如 course、日期等。 我尝试了以下方法:
Session.aggregate(
[
$match: $text: $search: 'web'
,
$unwind: '$course' ,
$project:
course: '$course',
date: '$date',
address: '$address',
available: '$available'
,
$group:
_id: title: '$course.title', category: '$course.courseCategory', language: '$course.language'
],
function(err, result)
if (err)
console.error(err);
else
Session.deepPopulate(result, 'course course.trainer
course.courseCategory', function(err, sessions)
res.json(sessions);
);
);
我的模型:
会话 schema = new mongoose.Schema(
date:
type: Date,
required: true
,
course:
type: mongoose.Schema.Types.ObjectId,
ref: 'course',
required: true
,
palnning:
type: [Schedule]
,
attachments:
type: [Attachment]
,
topics:
type: [Topic]
,
trainer:
type: mongoose.Schema.Types.ObjectId,
ref: 'trainer'
,
trainingCompany:
type: mongoose.Schema.Types.ObjectId,
ref: 'training-company'
,
address:
type: Address
,
quizzes:
type: [mongoose.Schema.Types.ObjectId],
ref: 'quiz'
,
path:
type: String
,
limitPlaces:
type: Number
,
status:
type: String
,
available:
type: Boolean,
default: true
,
createdAt:
type: Date,
default: new Date()
,
updatedAt:
type: Date
,
versionKey: false
);
课程
let schema = new mongoose.Schema(
title:
type: String,
required: true
,
description:
type: String
,
shortDescription:
type: String
,
duration:
type: Duration
,
slug:
type: String
,
slugs:
type: [String]
,
program:
content:
type: String
,
file:
type: String
,
audience: [String],
requirements: [String],
language:
type: String,
enum: languages
,
price:
type: Number
,
sections: [Section],
attachments:
type: [Attachment]
,
tags: [String],
courseCategory:
type: mongoose.Schema.Types.ObjectId,
ref: 'course-category',
required: true
,
trainer:
type: mongoose.Schema.Types.ObjectId,
ref: 'trainer'
,
trainingCompany:
type: mongoose.Schema.Types.ObjectId,
ref: 'training-company'
,
status:
type: String,
default: 'draft',
enum: courseStatus
,
path:
type: String
,
cover:
type: String,
required: true
,
duration:
type: Number,
min: 1
,
createdAt:
type: Date,
default: Date.now
,
updatedAt:
type: Date
,
versionKey: false
);
我不确定我所尝试的是否会给我带来我想要的,并且我收到了关于 $unwind 运算符的错误:
MongoError:异常:$unwind 字段路径“$course”末尾的值 必须是一个数组,但是是一个 OID
任何形式的帮助都将不胜感激。
【问题讨论】:
您缺少$lookup
,通过将课程对象 ID 从会话文档加入课程文档中的 ID 来提取课程文档。在$match
和$unwind
阶段之间插入查找阶段。像 $lookup: from: "course", localField: "course", foreignField: "_id", as: "course"
这样的东西。调整以使用正确的集合名称、本地字段和外部字段。
@Veeram 我收到了这个错误:MongoError: exception: Unrecognized pipeline stage name: '$lookup'
如果有意义的话,我的猫鼬版本是 ^4.11.12。
$lookup
阶段已添加到 3.2 mongo 服务器中。看起来你不在 3.2 版本上。进入 mongo shell 并运行db.version()
进行验证。
@Veeram mongo 版本 2.6.11
【参考方案1】:
您可以尝试以下聚合。
您缺少$lookup
需要通过将课程对象 ID 从会话文档加入课程文档中的 ID 来提取课程文档。
$project
阶段以在输出中保留所需的字段。
Session.aggregate([
"$match":
"$text":
"$search": "web"
,
"$lookup":
"from": "courses",
"localField": "course",
"foreignField": "_id",
"as": "course"
,
"$project":
"course": 1,
"date": 1,
"address": 1,
"available": 1
])
Course 是一个包含一个课程文档的数组。您可以使用$arrayElemAt
来投影文档。
"course": "$arrayElemAt":["$course", 0]
【讨论】:
它工作正常,除了添加 $match 时,即使条件为真,例如:` $match: 'available': true ` 您是否暗示当您添加“可用”以匹配阶段时它不起作用?像 "$match": "$text": "$search": "web" , "available": true
这样的东西应该可以工作。
不,即使只有 "$match": "available": true
也不起作用
实际上,即使在输出中我也没有得到 available 属性
很难推测。只需检查您的文件并确保它与您要查找的内容相符。可能是字符串“真”值。如果问题仍然存在,请考虑创建一个包含所有详细信息的单独问题。以上是关于带有全文搜索和项目的 Mongoose 子字段聚合的主要内容,如果未能解决你的问题,请参考以下文章