0

I am using auto schema to define an array field. I need to find documents where multiple specific values are contained in that array. I know I can use the $in: operator while $in: can only match either one of the value in the first array against the second array while I would need to match any record that have all value in the first array. How I can achieve this?

Schema Definition

Demands = new Mongo.Collection("demands");

var demandschema = new SimpleSchema({
  ability: {type:array},
  language: {type: array}});

Demands.attachSchema(demandschema);

Contents Definition

DemandsSet=[
  {ability: ["laser eye", "rocky skin", "fly"], language: ["english", "latin", "hindu"]},
  {ability: ["sky-high jump", "rocky skin", "fly"], language: ["english", "latin", "japanese"]},
  {ability: ["rocky skin", "sky-high jump"], language: ["english", "latin", "russian"]}
];

Target Set

var TargetAbility = ["rocky skin", "fly"];
var TargetLanguage = ["english", "hindu"];

When I do a $in operation

Demands.find({ $and: [
  { ability: { $in: TargetAbility }}, 
  { language: { $in: TargetLanguage }}
]}).fetch();

I will return me with all records, while it is not correct, how can I perform such a find operation?

3
  • At first your code is not valid at all… TargetAbility and TargetLanguage are supposed to be arrays, while the first argument in the find method must be an object. Content definition overrides the Collection object and is confounding objects with arrays Please fix before or people will only reply regarding the syntax instead of the problem itself. Commented Sep 26, 2015 at 5:53
  • Agreed his syntax is completely dorked, didn't have the patience to edit it. Commented Sep 26, 2015 at 5:55
  • Well sorry about the syntax error. Commented Sep 26, 2015 at 6:13

1 Answer 1

2

$in: is not going to work for you because it looks for any match when comparing two arrays, not that all elements of one array must be present in the other.

You can write complete javascript functions to execute the required comparisons inside the mongodb query. See $where:

For example:

Demands.find({$where:
  "this.ability.indexOf(TargetAbility[0])   > -1 &&
   this.ability.indexOf(TargetAbility[1])   > -1 &&
   this.language.indexOf(TargetLanguage[0]) > -1 &&
   this.language.indexOf(TargetLanguage[1]) > -1" });

If your candidates have other than 2 entries each then you can write a more general form of this of course.

Note that Meteor apparently does not support the function() form of $where: but that restriction may be dated.

Also note that $where: cannot take advantage of indexes so performance may not be suitable for large collections.

Sign up to request clarification or add additional context in comments.

1 Comment

Greatest thx for your help and advice. That saves my date. In that case, I will use a lot of boolean fields instead so as to speed up the query. Though it may taken extra effort on the ui side, i think it worth the time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.