简体   繁体   中英

How to find a document of an ID from an array in JavaScript (Mongoose)

I have a function on my server that is supposed to get a post by its ID. The function works up until the "foundPost" constant, where I can't seem to find one of the documents from the "posts" array. I've tried substituting findOne for find and the ObjectIds work for the const 'post'. I've double checked that post_id is 62067c1211eea1531d5872f4

Here is the function to find a post:

const postById = async (req, res) => {
    const userId = req.params.userId;
    const post_id = req.params.post_id;
    const posts = await Post.findOne({ user: userId });
    console.log(posts);  //see this below
    const foundPost = await posts.findOne({ "upload": post_id });  //error here
    console.log(foundPost);
    return res.json({ success: true, Post: foundPost });
};

Here is what 'console.log(posts)' returns:

[
   {
     upload: new ObjectId("623b681bdf85df9086417723"),
     edited: false,
     title: 'Test 1',
     description: 'testing post 1',
     name: 'John ',
     sharedPost: 0,
   },
   {
     upload: new ObjectId("62067c1211eea1531d5872f4"),
     edited: false,
     title: 'Test 2',
     description: 'testing post 2',
     name: 'John ',
     sharedPost: 0,
   }
]

I'm hoping that the function will return:

{
  success: true,
  {
     upload: new ObjectId("62067c1211eea1531d5872f4"),
     edited: false,
     title: 'Test 2',
     description: 'testing post 2',
     name: 'John ',
     sharedPost: 0,
   },
}

Can anyone see why the line const foundPost = await posts.findOne({ "upload": post_id }); isn't working? Thank you for your help.

****** Response to answer ******

Hello, thanks a lot for your answer, unfortunately it's still giving an error. Please see below the model for the code I'm using:

const PostSchema = new Schema({
  user: {
    type: Schema.Types.ObjectId,
    ref: "user",
  },
  post: [
    {
      user: {
        type: Schema.Types.ObjectId,
        ref: "user",
      },
      upload: {
        type: Schema.Types.ObjectId,
        ref: "upload",
      },
      title: {
        type: String,
      },
      description: {
        type: String,
      },
    },
  ],
  date: {
    type: Date,
    default: Date.now,
  },
});

I noticed that you used 'userProfile.posts' which I adapted to 'userProfile.post' to match this schema. I'm also not sure if you wanted to use 'subdoc' or 'subDoc' in line 11 of your code, but I tried both with the same error for each. I determined that the code stuck at the const subDocs = userPosts.filter(filter); line. I've looked into the.filter method you've used and can't find any potential errors. Not sure what the issue is.

Thanks

The issue is that you cannot run another mongo query on objects that were result of a previous query.

//will return a single document if found, or null if not found.
const posts = await Post.findOne({ user: userId });
//this will not work because at this point 'posts' will be either a Document or null value
//So the object will not have the method 'findOne' available.
const foundPost = await posts.findOne({ "upload": post_id });

The solution is to deal correctly with the types of objects you have.

Below is a functional and safe implementation that solves your issue:

const userPosts = await Post.findOne({ user: userId }).exec();
if (!userPosts) {
  // document not found with provided userId
  return res.json({ success: false });
}
//here we have a Document
//check if document has 'posts' property and is an array
if (userPosts.posts) {
  //filter the posts array

  const filter = function(subDoc) {
    return subdoc.upload === post_id
  }

  const subDocs = userPosts.filter(filter);
  //filter returns an array, so we must check if has itens
  //then we grab the first item
  if (subDocs.length > 0) {
    const foundPost = subDocs[0];
    return res.json({ success: true, Post: foundPost });
  }
  
  //subDoc not found, return correct response
  return res.json({ success: false });
}

If your Post model schema is what I'm supposing to be, this code will work perfectly.

const schema = mongoose.schema({
  user: Number,
  posts: [{ upload: Number }]
})

In case of error, please add the code of the model schema structure.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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