Persist data as an (unordered) set in MongoDB - mongodb

I am using MongoDB with node.js. Is it possible to persist data as an (unordered) set in MongoDB directly? Or do I have to either
persist them as an array and transform it into a set in JavaScript
or
persist them as an object in the form of {entry1: true, entry2: true, ...}
If I have to do it in either of the two ways above, which one is more efficient? Considering I need to add/remove items frequently, but rarely need to re-assign the whole set/array.

You can manipulate an array as a set in MongoDB... relevant operators include:
$addToSet - The $addToSet operator adds a value to an array only if the value is not in the array already.
$push - The $push operator appends a specified value to an array.
$pop - The $pop operator removes the first or last element of an array.
$pull - The $pull operator removes all instances of a value from an existing array.
$elemMatch - The $elemMatch operator matches more than one component within an array element.

Related

Push element in mongoDB, if it doesn't exist

I have many functions update with mongo
here is an example :
db.auto.update({'def.name':'AFFAIRES'},{$push:{
"covers":{$each: [{"a":'G06'},{"a":'G07'},{"a":'G03'},{"a":'G04'},{"a":'G07'},{"a":'G30'},{"a":'G34'},
{"cover":'G14'}]}}},{multi:true})
But,the problem, my collection may contain one of these variables "a", so i don't need to push it, and if it doesn't, i have to push it in the collection.
So my question is how to tell mongoDB to verify before the push, is it possible??
My query may contain other variables to push also.
Use $addToSet - The $addToSet operator adds a value to an array unless the value is already present. If the value is already present then the $addToSet does nothing to that array. $addToSet only ensures that there are no duplicate items added to the set and does not affect existing duplicate elements. $addToSet does not guarantee a particular ordering of elements in the modified set.

mongodb EmbedMany strategy=set

I had a collection with an embedMany attribute using strategy=set, so an ArrayCollection was stored. However we deleted some items from the array and now there are some documents with keys not sequential integers.
I need to solve this inconsistence, how can I do that?
You could use $type operator and query for all documents where your embedManyField is of type object. Once you have these documents, apply array_values to fields where array shall be stored and save them again. Also to avoid such situations in future you should change your collection's strategy to either setArray or atomicSetArray.

MongoDB Query Nested Array Search

I need to query documents with mongoDb that contain nested arrays. I see a lot of examples using the simple $in operator. The only problem is that I strictly need to check for proper subsets.
Consider the following document.
{data: [[1,2,3], [4,5,6]]}
The query needs to be able to get documents with all of [1,2,3] where 1,2,3 can be in any order, which rules out the following query, because it will only match in the correct order.
{data:{$elemMatch:{$all:[[1,2,3]]}}}
I've also tried nested $elemMatch operators with no success, because the $in operator will return the document even if only one element matches such as the following.
{data:{$elemMatch:{$elemMatch:{$in:[1,4]}}}}
Not sure what your actual query looks like, but this should do what you need:
db.documentDto.find({"some_field":{"$elemMatch":{"$in":[1,2,3]}} })
I haven't got a complete answer (and not much time as its late here) but I would consider
Using aggregation pipeline instead of a query if your not already
Use $unwind operator to deconstruct your nested arrays
Use $sort to sort the contents of the arrays - so you can now compare
Use $match to filter out the arrays which don't fit the array subset values as you can now check based on order.
Use $group to group the result back together based on the _id value
Ref:
http://docs.mongodb.org/manual/reference/operator/aggregation-pipeline/ will give you info on each of the above.
From a quick search I came up with a similar question/example that might be helpful: Mongodb sort inner array

MongoDB unwind empty array and not ignoring input document

In this case How do I keep documents in aggregation with $unwind aggregation can be ommited but what if you have a more complex case where you need aggregation framework? How can you keep these documents and still unwind those who have non-empty lists?
My case involves aggregation pipeline with multiple stages (match, unwind, project, match, group,..), i simply cannot fallback to plain "match" because those nested arrays need to be presented in a form of report (JasperReports). I first thought that this $unwind empty array will solve my problem but it won't because this array needs to be empty since I'm later grouping these values in JasperReport and showing them as they are.
I hope I was clear enough.
Any ideas?
Starting from MongoDb 3.2, $unwind operator supports preserveNullAndEmptyArrays:<boolean>.
So when preserveNullAndEmptyArrays:true, it will also include value which doesn't have any data or empty data.
for more info, visit - https://docs.mongodb.com/manual/reference/operator/aggregation/unwind/#document-operand-with-options

Mongodb - proper way to delete all elements in an array field?

I'm looking for the proper way to remove all elements from an array field (across all documents) in Mongodb - these appear to be equivalent, which is recommended: (or perhaps some other way?)
db.collection.update({}, { $pull : { 'myArray': {} }}, {multi:true} )
or
db.collection.update({}, { $set : {'myArray': [] }} , {multi:true} )
The $set variant will be faster as the $pull will have to do calculations on arrays. I am actually not even certain whether it will work, as you're not really removing any elements with your query.
Just to make sure, do you need to keep an empty array? Because otherwise, it's probably better to $unset it.
If you must keep an empty array, I believe your $pull call won't work - I think it will remove all empty elements from your array, not all elements.
According to Mongodb's official document:
When used with $ to match an array element, $unset replaces the
matching element with null rather than removing the matching element
from the array. This behavior keeps consistent the array size and
element positions.
The $set should be the proper way.