1

I have documents containing lists of keywords. How can I query such that a search for e.g., the keywords bela and fleck returns only documents that have both of those keywords:

{
    "_id": "track/bela-fleck/big-country",
    "title": "Big Country",
    "artist": "Bela Fleck",
    "keywords": ["bela", "fleck", "big", "country"]
}
spiffytech
  • 5,185
  • 5
  • 36
  • 51

2 Answers2

1

This can be done with a Mango query. First, create an index on the keywords field:

{
   "index": {
      "fields": [
         "keywords"
      ]
   },
   "name": "keywords-index",
   "type": "json"
}

Then, query using $elemMatch to find items in the array matching each keyword, and $and to find documents that match all keywords:

{
   "selector": {
      "keywords": {
         "$and": [
            {
               "$elemMatch": {
                  "$eq": "bela"
               }
            },
            {
               "$elemMatch": {
                  "$eq": "fleck"
               }
            }
         ]
      }
   }
}

Note that this method does not use indexes to search inside the array.

spiffytech
  • 5,185
  • 5
  • 36
  • 51
0

Something like this could work:

function map(doc) {
  // sort by each keyword
  for (var k in doc.keywords) {
    emit(doc.keywords[k], null);
  }      
}

db.query(map).then(function (result) {
  // handle result
}).catch(function (err) {
  console.log(err);
});

...but I have not tested it! Also this does a full database scan, so for efficiency you should create a view in design doc as described in the PouchDb API documentation for Map/Reduce. Hope this helps.

Update... the CouchDb guide also has some detailed examples that may help.

IanC
  • 740
  • 7
  • 11
  • I don't think it will work with CouchDB 2.X as temporary view are not supported. The suggested way would be to define a view in a design document with the same mapping function. – Alexis Côté Aug 03 '18 at 19:58