0

I have a document like bellow:

books: [
{_id: 1,chapters:{0:{title:'ch1'},1:{title:'ch2'},2:{title:'ch3'}},description:'book one'},
{_id: 2,chapters:{0:{title:'ch4'},1:{title:'ch2'},2:{title:'ch5'}},description:'book two'},
{_id: 3,chapters:{0:{title:'ch6'},1:{title:'ch7'},2:{title:'ch8'}},description:'book three'},
{_id: 4,chapters:{0:{title:'ch9'},1:{title:'ch10'},2:{title:'ch11'}},description:'book four'}
]

so my question is this : how can i find object in this collection that has a chapter with title of 'ch2' ? and i can't change the data and structure of that!

perhaps this is a help: i using embedded document from jenssegers/laravel-mongodb. if there is a better library for using mongodb in laravel please let me know! thanks

1 Answers1

0

Since your collection is huge 100m, try indexing the fields, and do $text search on collection

creating text index

https://docs.mongodb.com/manual/core/index-text/

$text search

https://docs.mongodb.com/manual/reference/operator/query/text/index.html

> db.books.ensureIndex({"$**" : "text"})

index

{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 2,
    "numIndexesAfter" : 2,
    "note" : "all indexes already exist",
    "ok" : 1
}

result

> 
> db.books.find({$text : {$search : "ch2"}})
{ "_id" : 2, "chapters" : { "0" : { "title" : "ch4" }, "1" : { "title" : "ch2" }, "2" : { "title" : "ch5" } }, "description" : "book two" }
{ "_id" : 1, "chapters" : { "0" : { "title" : "ch1" }, "1" : { "title" : "ch2" }, "2" : { "title" : "ch3" } }, "description" : "book one" }
> 

This is possible with out text index, by to converting the chapters $objectToArray for searching and back to $arrayToObject, but this will do this for 100m documents, not suitable for your case

db.books.aggregate(
    [
        {$project : { description : 1, arr : {$objectToArray : "$$ROOT.chapters"}}}, 
        {$match : {"arr.v.title" : "ch2"}}, 
        {$project : { description : 1 , chapters : { $arrayToObject : "$$ROOT.arr"}}}
    ]
).pretty()

result

> db.books.aggregate([{$project : { description : 1, arr : {$objectToArray : "$$ROOT.chapters"}}}, {$match : {"arr.v.title" : "ch2"}}, {$project : { description : 1 , chapters : { $arrayToObject : "$$ROOT.arr"}}}])
{ "_id" : 1, "description" : "book one", "chapters" : { "0" : { "title" : "ch1" }, "1" : { "title" : "ch2" }, "2" : { "title" : "ch3" } } }
{ "_id" : 2, "description" : "book two", "chapters" : { "0" : { "title" : "ch4" }, "1" : { "title" : "ch2" }, "2" : { "title" : "ch5" } } }
> 
Saravana
  • 12,647
  • 2
  • 39
  • 57