Does document db support "not in" - aws-documentdb

Does document db support NOT IN operator. I can see in this document https://docs.aws.amazon.com/documentdb/latest/developerguide/querying.html other examples but not for this. Need help with syntax to have something like
db.example.find( NOT IN { "Item": ["item1","item2"]} AND {"Code":"code1"} ).pretty()

DocumentDB supports $nin operator and you can use this operator to select documents where the field is not in a specified array. Please find below the updated query.
db.example.find({ $and: [{Item: {$nin:["item1","item2"]}} , {Code:"code1"}] })

Related

MongoDB $nin + $elemMatch behaviour

When trying to do a $nin match with $elemMatch in .net I get no results. I've reconstructed the statement on Mongo Playground.
I guess I'm missing something around the $nin but can't find anything in the docs.
This post is talking about the issue but the solution they gave doesn't work if you set the data up with a valid exclude.
I've read through the docs and a few posts around this issue, I'm assuming there is a gap in my knowledge around how $nin and or $elemMatch works, I hope someone can point me in the correct direction and possible fix the example on mongo playground.
You are mistaking the behaviour of $elemMatch. $elemMatch will return the document if any of the array element match your criteria.
For your expected behaviour, you can simply do:
db.collection.aggregate([
{
$match: {
"ingredient.name": {
$nin: [
"X"
]
}
}
}
])
Mongo Playground

MongoDB conditional query on nested document array

Hi I'm trying to write a conditional query on nested document array.
I've read the document for days and couldn't figure out how to make this work.
DB looks like below :
[
{
"id":1,
"team":"team1",
"players":[
{
"name":"Mario",
"substitutes":[
"Luigi",
"Yoshi"
]
},
{
"name":"Wario",
"substitutes":[
]
}
]
},
{
"id":2,
"team":"team2",
"players":[
{
"name":"Bowser",
"substitutes":[
"Toad",
"Mario"
]
},
{
"name":"Wario",
"substitutes":[
]
}
]
}
]
Due to my lack of English, it's hard to put but what I'm trying to do is
to find teams that includes all queried players.
Each object in players array, some have substitutes.
For each objects in players array, if one of the queried players is not the main player("players.name"), then I want it to look for if one of substitutes("players.substitutes") is.
Team.find({players:{$in:[ 'Mario', 'Wario' ]}}) (mongoose query)
this will give me an array with 'team1'.
but what I want to get is both teams because 'Mario' is one of the substitutes for 'Bowser'(team2).
I failed to make a query but what I've been trying is not to use $where since the official MongoDB docs says :
AGGREGATION ALTERNATIVES PREFERRED
Starting in MongoDB 3.6, the $expr operator allows the use of
aggregation expressions within the query language. And, starting in
MongoDB 4.4, the $function and $accumulator allows users to define
custom aggregation expressions in JavaScript if the provided pipeline
operators cannot fulfill your application’s needs.
Given the available aggregation operators:
The use of $expr with aggregation operators that do not use JavaScript
(i.e. non-$function and non-$accumulator operators) is faster than
$where because it does not execute JavaScript and should be preferred
if possible. However, if you must create custom expressions, $function
is preferred over $where.
BUT if it could be easily written with $where operator then it's totally fine.
Any suggestions or ideas that lead to any further would be highly appreciated.
Firstly, your query is incorrect. And it is not very obvious what exactly is your filter criteria. So I am giving two suggestions:
If you want to filter all documents that have name defined in your matching criteria (which returns both documents):
db.Team.find({"players.name":{$in:[ 'Mario', 'Wario' ]}}).pretty()
If you want to filter all documents that have any provided player names in the substitutes array (which returns only one, because team1 doesn't have any substitutes are Mario/Wario)
db.Team.find({"players.substitutes":{$in:[ 'Mario', 'Wario' ]}}).pretty()
The names being looked at could be present in name or substitute
db.Team.find({ $or: [{"players.substitutes":{$in:[ 'Mario', 'Wario' ]}}, {"players.name":{$in:[ 'Mario', 'Wario' ]}}] }).pretty()

MongoDB: How To Save Returned Results To Another Collection?

Consider the following:
I have a MongoDB collection named C_a. It contains a very large number of documents (e.g., more than 50,000,000).
For the sake of simplicity let's assume that each document has the following schema:
{
"username" : "Aventinus"
"text": "I love StackOverflow!",
"tags": [
"programming",
"mongodb"
]
}
Using text index I can return all documents which contain the keyword StackOverflow like this:
db.C_a.find({$text:{$search:"StackOverflow"}})
My question is the following:
Considering that the query above may return hundreds of thousands of documents, what is the easiest/fastest way to directly save the returned results into another collection named C_b?
Note: This post explains how to use aggregate to find exact matches (i.e., specific dates). I'm interested in using Text Index to save all the posts which include a specific keyword.
The referenced answer is correct. The example query from that answer can be updated to use your criteria:
db.C_a.aggregate([
{$match: {$text: {$search:"StackOverflow"}}},
{$out:"C_b"}
]);
From the MongoDB documentation for $text:
If using the $text operator in aggregation, the following restrictions also apply.
The $match stage that includes a $text must be the first stage in the pipeline.
A text operator can only occur once in the stage.
The text operator expression cannot appear in $or or $not expressions.
The text search, by default, does not return the matching documents in order of matching scores. Use the $meta aggregation expression in the $sort stage.

Mongo DB: What are the Performance issues in using $all

I am trying to search a list of values on a matching field in documents which is array of documents. Using $in makes it OR between the values I supply. Using $all seems to be more logical.
For eg:
Collection: Phrases
sample doc:
{
"locales": [
{
"name": "BPT",
"internal_desc": "Entre 2 e 3 horas"
},
{
"name": "JPN",
"internal_desc": "2 ~ 3 時間"
}
]
}
Query:
db.phrases.find({"locales.name":{"$all":["BPT", "JPN"]}})
But some posts suggesting $all is bad in terms of performance. Is there any other way to achieve this?
Using $and instead of $all will result in equivalent performance. The bottom line is that given what you are trying to accomplish using $all is your best bet (as far as my understanding goes). However, $all can be optimized by making the first element in the expression more selective. For example if you know that "BPT" shows up in 2% of documents and "JPN" shows up in 20% of documents then it makes sense to list "BPT" as the first element in the $all expression. This way mongo only needs to filter through fewer documents on each consecutive element in your $all expression. Im sure you've seen the documentation but here is a link nonetheless: $all - mongodb
You can use the $and syntax, as shown in the query below;
db.phrases.find({$and : [
{"locales.name" : "BPT"},
{"locales.name" : "JPN"}
]
});
You can get information about your query, to see what the db is doing when executing the query by using the explain command, as displayed below;
db.phrases.explain().find({$and : [
{"locales.name" : "BPT"},
{"locales.name" : "JPN"}
]
});
Although, the explain command is more relevant to dbs where indexes are used, since it sort of gives you information about, which index was utilised by the db on the search.
Have a quick look into MongoDB indexes and explain() for further information.
I hope this helps.
Regards,
Nick.

mongodb $addToSet failure, specify full document to insert

I've done a bit of research on this and haven't come across anything that jumps out at me immediately as what I'm looking for.
Say we have a document (or documents) in a collection that look something like this:
//First example document
{
"_id": "JK",
"letters": ["J", "K"]
}
//Second example document
{
"_id": "LM",
"letters": ["L"]
}
So I run a query like the one below to see if I have any matching documents and of course I don't so I expect to get null.
> db.example.findOne({"_id": "LM", "letters": {"$in": ["M"]}})
null
So I do an update and add "M" to the letters array on the documents (syntax may not be quite right):
> db.example.update({"_id": "LM"}, {"$addToSet": {"letters": "M"}})
I run the possibility of not having a matching _id, so the findOne would would also return null given the example documents in the collection for this query.
> db.example.findOne({"_id": "AB", "letters": {"$in": ["A"]}})
null
Based on the way I've constructed the above query, I get null back when "A" is not found in letters or the _id of "AB" is not found on any document. In this case I know that this document isn't in there because I know what is in the collection.
What I'd like to do is keep my update query from above with $addToSet and modify it to use upsert WHILE ALSO specifying the document to insert in the event that $addToSet fails due to the document not existing to cut down on database transactions. Is this possible? Or will I have to break up my queries a bit in order to accommodate this?
Because this information may influence answers:
I do my querying through mongo shell and pymongo.
mongo version: 2.6.11
pymongo version: 2.8
Thanks for any help!
EDIT: So after a break and a bit more digging, it seems setOnInsert does what I was looking for. I do believe that this probably solves my issue, but I've not had a chance to test yet.