Meteor.find multiple values in an array - meteor

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?

$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.

Related

Weaviate: using near_text with the exact property doesn't return a distance of 0

Here's a minimal example:
import weaviate
CLASS = "Superhero"
PROP = "superhero_name"
client = weaviate.Client("http://localhost:8080")
class_obj = {
"class": CLASS,
"properties": [
{
"name": PROP,
"dataType": ["string"],
"moduleConfig": {
"text2vec-transformers": {
"vectorizePropertyName": False,
}
},
}
],
"moduleConfig": {
"text2vec-transformers": {
"vectorizeClassName": False
}
}
}
client.schema.delete_all()
client.schema.create_class(class_obj)
batman_id = client.data_object.create({PROP: "Batman"}, CLASS)
by_text = (
client.query.get(CLASS, [PROP])
.with_additional(["distance", "id"])
.with_near_text({"concepts": ["Batman"]})
.do()
)
print(by_text)
batman_vector = client.data_object.get(
uuid=batman_id, with_vector=True, class_name=CLASS
)["vector"]
by_vector = (
client.query.get(CLASS, [PROP])
.with_additional(["distance", "id"])
.with_near_vector({"vector": batman_vector})
.do()
)
print(by_vector)
Please note that I specified both "vectorizePropertyName": False and "vectorizeClassName": False
The code above returns:
{'data': {'Get': {'Superhero': [{'_additional': {'distance': 0.08034378, 'id': '05fbd0cb-e79c-4ff2-850d-80c861cd1509'}, 'superhero_name': 'Batman'}]}}}
{'data': {'Get': {'Superhero': [{'_additional': {'distance': 1.1920929e-07, 'id': '05fbd0cb-e79c-4ff2-850d-80c861cd1509'}, 'superhero_name': 'Batman'}]}}}
If I look up the exact vector I get 'distance': 1.1920929e-07, which I guess is actually 0 (for some floating point evil magic), as expected.
But if I use near_text to search for the exact property, I get a distance > 0.
This is leading me to believe that, when using near_text, the embedding is somehow different.
My question is:
Why does this happen?
With two corollaries:
Is 1.1920929e-07 actually 0 or do I need to read something deeper into that?
Is there a way to check the embedding created during the near_text search?
here is some information that may help:
Is 1.1920929e-07 actually 0 or do I need to read something deeper into that?
Yes, this value 1.1920929e-07 should be interpreted as 0. I think there are some unfortunate float32/64 conversions going on that need to be rooted out.
Is there a way to check the embedding created during the near_text search?
The embeddings are either imported or generated during object creation, not at search-time. So performing multiple queries on an unchanged object will utilize the same search vector.
We are looking into both of these issues.

Bookshelf's nested query

I'm trying to get the following query in bookshelf's, any ideas? (this query is working and returns the required result)
SELECT "restaurants".*, "meals".*, ( select count(*) from "public"."visitors" as "visitors" where "visitors"."meal_id" = "meals"."id") as "visitorsMealsCount" FROM "public"."restaurants" as "restaurants" inner join "public"."meals" as "meals" ON "meals"."restaurant_id" = "restaurants"."id" WHERE "restaurants"."id" = '123'
Another question, after I'm using belongsTo and hasMany (for example) i expected the return object will be similar to that
restaurants (obj)
meals (obj)
visitorsMealsCount (attribute)
to me your SQL statement doesn't match the concept of an ORM tool like Bookshelf - it neither returns restaurants nor meals, but a grand mixture.
As to your second question: How about using new Restaurant({id: '123'}).fetch({ withRelated: ['meals']}) ?
visitorsMealsCount: In the documentation I see
adminAccounts: function() {
return this.belongsToMany(Account).query({where: {access: 'admin'}});
},
so maybe
visitorsMealsCount: function() {
return this.belongsToMany(Visitor).count();
}
works? (I haven't tried it.)

dynamodb: how to increment a value in map

I am trying to use dynamodb to maintain a map of names with their values
eg. {"scores": {"player-a": 10}}
I also wish to use increment operator to perform atomic increments.
However, i could find very little documentation on how to use/update dynamodb maps.
Here's the python code I have so far
import boto3
ddb = boto3.client('dynamodb')
ddb.update_item(TableName='ledger', Key={'week': {'S': '06-12'}},
UpdateExpression='SET scores.player-a = scores.player-a + :val',
ExpressionAttributeValues={':val': {'N': '12'}})
DynamoDB update item uses ExpressionAttributeNames to prevent special characters in an attribute name from being misinterpreted in an expression.
Your update item consists of "player-a" as a key name which has "-" (hyphen) in it.
ddb.update_item(
TableName='ledger',
Key={
'week': {
'S': '06-12'
}
},
UpdateExpression='SET scores.#s = scores.#s + :val",
ExpressionAttributeNames={
"#s": "player-a"
},
ExpressionAttributeValues={
':val': {
'N': '12'
}
}
)

METEOR - Automatically increment order numbers

What I need to do is use either collection-2 or another package to automatically create a new order number, incremented from the last order number used.
i.e. Starting off with PO123456, when I save this order, the next time I make a new PO, it automatically generates the number PO123457.
I've been looking for a good example or tutorial, but I'm not able to find one.
Using konecty:mongo-counter in conjuntion with aldeed:collection2 and aldeed:simple-schema should be pretty straightforward. In your schema definition try:
POnumber: { type: String, autoValue: function(){
if ( this.isInsert ){ // restrict to when inserting a document
var currentNumber = incrementCounter('purchase order'); // this will use mongo-counter
// WARNING: you can only ever get as rich as 10M POs!!
var zeroPad = "000000" + currentNumber; // pad with 6 zeros
zeroPad = zeroPad.substr(zeroPad.length-7); // restrict to 7 places
return 'PO' + zeroPad; // prefix with 'PO'
} else if ( this.isSet ){
this.unset(); // prevent attempts to change the number
}
}

Scala MongoDB Casbah need to build a dynamic $or query

Using Scala, MongoDB, Casbah.
Given a random list of strings:
val names = {
val listBuffer = new ListBuffer[String]
for(n <- 1 to (new Random().nextInt(5) + 1)){
val name = ((new Random().nextInt(26) + 65).asInstanceOf[Char]).toString
listBuffer += name
}
listBuffer.toList
}
Given a MongoDB document structure:
"_id": <uuid>
"name": <string>
How do I find all documents that have a name equal to an entry in my list using a single single MongoDBCollection.find() statement? (i.e using $or)
Thanks,
- Don
MongoDB has conditional operator $in that lets test if a field's value is in a list of values (documentation)
collection.find({name: {$in: ["aaa", "bbb", "ccc"]}})
In Casbah this will look like
collection.find("name" $in names)

Resources