3

I used to have a Comment schema, where I held author, comment and commentID fields, essentially duplicating author's name for every comment that belonged to him. So I refactored it as following. Now I have an Author model with an array of his comments, it does feel better but I've lost the ability to query commentBody via fulltext search. Before I would just query Comment model with the term and it returned me every comment that met the criteria.

const authorSchema = new mongoose.Schema({
  name: { type: String, unique: true, index: true },
  comments: [{
    commentID: { type: String, unique: true },
    commentBody: { type: String, index: 'text' },
    created_at: { type: Date, default: Date.now }
  }],
  ...
  // other unrelated fields
});

But now when I'm trying to query Author model directly like this:

Author.find({ $text: { $search: `${req.params.term}` } })
  .select('name comments')
  .exec((error, result) => {
    res.json(result);
  });

it righteously so returns me every match of Author if at least one of his comments meets searching criteria. I've spent couple of hours reading Mongoose and MongoDB's docs, but I still can't write a proper query that will return only matched comments within the comments array, i.e. for term lorem I want the follow response:

{
  name: "Jane",
  comments: [
    {
      commentBody: "Lorem dolor",
      commentID: "42",
    },
    {
      commentBody: "Lorem lipsum.",
      commentID: "43",
    },
  ]
},
{
  name: "Doe",
  comments: [
    {
      commentBody: "Dolor lorem",
      commentID: "44",
    },
    {
      commentBody: "Lipsum lorem.",
      commentID: "45",
    },
  ]
}
curious_gudleif
  • 572
  • 1
  • 4
  • 19
  • MongoDB does not "filter" arrays within documents in search results, other than for a basic case to return the "first matched" element, but with normal queries and not "text" ones. Chances are you really want a [`$regex`](https://docs.mongodb.org/manual/reference/operator/query/regex/) query along with the general process in [Retrieve only the queried element in an object array in MongoDB collection](http://stackoverflow.com/questions/3985214/retrieve-only-the-queried-element-in-an-object-array-in-mongodb-collection). – Neil Lunn Apr 10 '16 at 22:11
  • But really, unless this is discarding 100's of array elements per document that do not match the conditions then just "filter the arrays" returned in the documents in your client code. The database is doing it's job by returning the "documents" that match conditions, and even in the "order of relevance" which is what a "text" search is actually for. As said, if you expect something else then you actually meant to use `$regex` instead. – Neil Lunn Apr 10 '16 at 22:13
  • @NeilLunn thank you for the response. I think regex would be quite slow, as the database is pretty large and search requests initiated from client are frequent. Filtering on the client is not an option either, since there are like a hundred of authors with dozens of thousands comments. Although it was pretty fast when I stored every comment separately and could utilize text index, now it seems that I should try to setup sphinx or elastic for the designated search purpose. – curious_gudleif Apr 11 '16 at 07:41

0 Answers0