【问题标题】:Mongoose sub field aggregation with full text search and project带有全文搜索和项目的 Mongoose 子字段聚合
【发布时间】:2018-03-29 11:11:21
【问题描述】:

我有一个名为 SessionMongoose 模型,其中有一个名为 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

标签: node.js mongodb mongoose aggregation-framework


【解决方案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 属性
  • 很难推测。只需检查您的文件并确保它与您要查找的内容相符。可能是字符串“真”值。如果问题仍然存在,请考虑创建一个包含所有详细信息的单独问题。
猜你喜欢
  • 2020-05-20
  • 2021-07-04
  • 1970-01-01
  • 1970-01-01
  • 2021-05-15
  • 1970-01-01
  • 2023-03-22
  • 2019-10-05
  • 2015-03-13
相关资源
最近更新 更多