Tacaza
Tacaza

Reputation: 559

Query documents that has any field containing a set of values

A document in my collection looks like this:

{
  'one':['a', 'b', 'c'],
  'two':['d', 'e'],
  'three':['f', 'g', 'h', 'i'],
  ...
  'twelve': ['x', 'y', 'z']
}

There are twelve such fields ('one', 'two', 'three'..) in a document, and there are 110 values ('a', 'b', 'c'...) that will be assigned as array elements to these fields randomly, but a value will only get assigned ONCE.

How do I find documents where the value of a field - ANY field - is an array that contains 'b', 'e', 'f' (all of them, and order does not matter) as its elements (it may contain other elements). A matching document may look like:

{
  'one':['a', 'c'],
  'two':['b', 'x', 'f', 'e'],
  'three':['z', 'h', 'g']
  ...
}

This document matches because it has a field ('two') which contains all 'b', 'e', 'f'.

Please note 'b', 'e', 'f' are just an example of search parameters. It may as well be 'h', 'g', or 'k', 'l', 's', 'b'. But the max number of search parameters should not exceed 5.

How can I write the query, or map-reduce functions to find documents this way? Or how should I restructure the document model to make this kind of search possible? I'm even open to suggestions about other databases (sql or document-based or any other kind) that may help with this kind of search.

Upvotes: 0

Views: 220

Answers (1)

Ivan.Srb
Ivan.Srb

Reputation: 1851

You could try to restructure like this:

db.collection.insert({
    properties: [
        { name: 'one', values: ['a', 'b', 'c']},
        { name: 'two', values: ['d', 'e']},
        { name: 'three', values: ['f', 'g', 'h', 'i']}
    ]
})

And find with this query:

db.collection.find({"properties": { $elemMatch: { values: { $all: [ 'f', 'h' ] }}}})

Also, you may do many other things with this scheme, for example find document where the values of any property is an array contains any of elements:

db.collection.find({"properties": { $elemMatch: { values: { $in: [ 'f', 'h' ] }}}})  

Also, you could find by property name and do all other things, that you could do with your old scheme.

Upvotes: 2

Related Questions