简体   繁体   English

如何在数组中查询带有猫鼬的子文档?

[英]How can I query an Array for a subdocument with mongoose?

I am looking to query a subdocument that contains an array. 我正在寻找一个包含数组的子文档。

You can think of this as an application similar to medium.com or tumblr.com: 您可以将其视为类似于medium.com或tumblr.com的应用程序:

I have a user schema, and User's have many Posts. 我有一个用户架构,而用户的帖子很多。 My post schema has a 'tags' key which is an array I am trying to create a route which will display all posts that have a certain tag. 我的帖子架构有一个“标签”键,这是我试图创建一个路由的数组,该路由将显示具有特定标签的所有帖子。

So for instance, 例如

GET /user/posts/:tag
GET /user/posts/dogs

might return back the data for all posts (by any user) that have the tag 'dogs' 可能会返回所有带有标签“狗”的帖子(由任何用户)的数据

{
  description: 'dogs are cool',
  title: 'huskies',
  tags: ['dogs','animals','outdoors'],
  original_poster: '34255352426'
},{
  description: 'My puppies are nice',
  title: 'Puppies',
  tags: ['pugs','dogs','small'],
  original_poster: '44388342426'
},{
  description: 'I like cats more than dogs',
  title: 'Cats',
  tags: ['kittens','cats','dogs'],
  original_poster: '15708213454'
} 

Here is my User Schema: 这是我的用户架构:

const mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    PostSchema = require('./post-model.js');

let UserSchema = new Schema({
    email: {
        type: String,
        required: true,
        unique: true
    },
    username: {
        type: String,
        required: true,
        unique: true
    },
    password: {
        type: String,
        required: false, //only required for local users
        unique: false,
        default: null
    },
    following: {
        type: [Number], 
        required: false,
        unique: false
    },
    followers: {
        type: [Number],
        required: false,
        unique: false
    },
    posts: [PostSchema],
})

module.exports = mongoose.model('User',UserSchema);

Here is my Post Schema: 这是我的发布架构:

const mongoose = require('mongoose'),
    Schema = mongoose.Schema;

let PostSchema = new Schema({
    description: {
        type: String,
        required: false,
        unique: false
    },
    title: {
        type: String,
        required: false,
        unique: false
    },
    tags: {
        type: [String],
        required: true
    },
    original_poster: { 
      type: String,
      required: true
    }
});

module.exports = PostSchema;

EDIT: 编辑:

to clarify my question, imagine that this was a regular js object, here is what a function to return all data relevant to a specific tag: 为了澄清我的问题,假设这是一个常规的js对象,这是一个返回与特定标签相关的所有数据的函数:

let users = [];
let user1 = {
  username: 'bob',
  posts: [
    {
      title: 'dogs r cool',
      tags: ['cats','dogs']
    },
    {
      title: 'twd is cool',
      tags: ['amc','twd']
    }]
};
let user2 = {
  username: 'joe',
  posts: [{
    title: 'mongodb is a database system that can be used with node.js',
    tags: ['programming','code']
  },
  {
    title: 'twd is a nice show',
    tags: ['zombies','horror-tv','amc']
  },
    {
      title: 'huskies are my favorite dogs',
      tags: ['huskies','dogs']
    }]
}

users.push(user1);
users.push(user2);

function returnPostByTag(tag) {
  let returnedPosts = [];

  users.forEach((user,i) => {
    user.posts.forEach((post) => {
      if(post.tags.includes(tag)) {
        let includespost = {}
        includespost.title = post.title;
        includespost.tags = post.tags;
        includespost.original_poster = user.username;
        returnedPosts.push(includespost);
      }
    })
  })
  return returnedPosts;
}

If you want to see a full repl where I use a plain js example here it is: https://repl.it/repls/LavenderHugeFireant 如果您想在我使用纯js示例的地方看到完整的repl,则为: https : //repl.it/repls/LavenderHugeFireant

You can do the following using Mongoose to return all users where the tags array in any of the subdocuments in the posts array includes tag : 您可以使用Mongoose进行以下操作,以返回所有用户,其中posts数组的任何子文档中的tags数组包含tag

User.find({ 'posts.tags': tag }, function(err, users) {
  if (err) {
    // Handle error
  }

  let filteredPosts = users
    .map(user => {
      user.posts.forEach(post => post.original_poster = user.username)
      return user
    })
    .map(user => user.posts)
    .reduce((acc, cur) => acc.concat(cur), [])
    .filter(post => post.tags.includes(tag))

  // Do something with filteredPosts
  // ...such as sending in your route response
})

...where User is your Mongoose model and tag contains the tag string you want to query (perhaps from your route request). ...其中User是您的Mongoose模型, 标签包含您要查询的标签字符串(可能来自您的路线请求)。

If you are using promises then you could do: 如果您使用诺言,则可以执行以下操作:

User.find({ 'posts.tags': tag })
  .then(users => {

    let filteredPosts = users
      .map(user => {
        user.posts.forEach(post => post.original_poster = user.username)
        return user
      })
      .map(user => user.posts)
      .reduce((acc, cur) => acc.concat(cur), [])
      .filter(post => post.tags.includes(tag))

    // Do something with filteredPosts
    // ...such as sending in your route response

  })
  .catch(err => {
    // Handle error
  })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM