I'm creating a query but i came a section when i don't have idea that how do it. I have one array that have for example two items
//filter array
const filterArray=r.expr(['parking', 'pool'])
and also i have one table with follows records:
[
{
"properties": {
"facilities": [
"parking"
],
"name": "Suba"
}
},
{
"properties": {
"facilities": [
"parking",
"pool",
"pet friendly"
],
"name": "Kennedy",
}
},
{
"properties": {
"facilities": [
"parking",
"pool"
],
"name": "Soacha"
}
},
{
"properties": {
"facilities": [
"parking",
"pet friendly",
"GYM"
],
"name": "Sta Librada"
}
},
]
I need filter the records with the array but i need that record has all items of array filter. If the record has more item of array filter not is problem, i need if contains all items of array filter get that record. On this case I need all records that have the facilities "pool" and "parking"
Current query
Current query but it also return records with one or two items of the filter array
r.db('aucroom').table('hosts')
.filter(host=>
host('properties')('facilities').contains(val=>{
return filterArray.contains(val2=>val2.eq(val))
})
)
.orderBy('properties')
.pluck(['properties'])
results that I desire wait
Like the image example:
If you want a strict match of two arrays (same number of elements, same order), then use .eq()
array1.eq(array2)
If you want the first array to contain all elements of the second array, then use .setIntersection(), just note array2 should contain distinct elements (a set):
array1.setIntersection(array2).eq(array2)
Related
I have a document that holds lists containing nested objects. The document simplified looks like this:
{
"username": "user",
"listOne": [
{
"name": "foo",
"qnty": 5
},
{
"name": "bar",
"qnty": 3
},
],
"listTwo": [
{
"id": 1,
"qnty": 13
},
{
"id": 2,
"qnty": 9
},
]
}
And I need to update quantity in lists based on an indentifier. For list one it was easy. I was doing something like this:
db.collection.findOneAndUpdate(
{
"username": "user",
"listOne.name": name
},
{
$inc: {
"listOne.$.qnty": qntyChange,
}
}
)
Then I would catch whenever find failed because there was no object in the list with that name and nothing was updated, and do a new operation with $push. Since this is a rarer case, it didn't bother me to do two queries in the database collection.
But now I had to also add list two to the document. And since the identifiers are not the same I would have to query them individually. Meaning four searches in the database collection, in the worst case scenario, if using the same strategy I was using before.
So, to avoid this, I wrote an update using an aggregation pipeline. What it does is:
Look if there is an object in the list one with the queried identifier.
If true, map through the entire array and:
2.1) Return the same object if the identifier is different.
2.2) Return object with the quantity changed when identifier matches.
If false, push a new object with this identifier to the list.
Repeat for list two
This is the pipeline for list one:
db.coll1.updateOne(
{
"username": "user"
},
[{
"$set": {
"listOne": {
"$cond": {
"if": {
"$in": [
name,
"$listOne.name"
]
},
"then": {
"$map": {
"input": "$listOne",
"as": "one",
"in": {
"$cond": {
"if": {
"$eq": [
"$$one.name",
name
]
},
"then": {
"$mergeObjects": [
"$$one",
{
"qnty": {
"$add": [
"$$one.qnty",
qntyChange
]
}
}
]
},
"else": "$$one"
}
}
}
},
"else": {
"$concatArrays": [
"$listOne",
[
{
"name": name,
"qnty": qntyChange
}
]
]
}
}
}
}
}]
);
Entire pipeline can be foun on this Mongo Playgorund.
So my question is about how efficient is this. As I am paying for server time, I would like to use an efficient solution to this problem. Querying the collection four times, or even just twice but at every call, seems like a bad idea, as the collection will have thousands of entries. The two lists, on the other hand, are not that big, and should not exceed a thousand elements each. But the way it's written it looks like it will iterate over each list about two times.
And besides, what worries me the most, is if when I use map to change the list and return the same object, in cases where the identifier does not match, does MongoDB rewrite these elements too? Because not only would that increase my time on the server rewriting the entire list with the same objects, but it would also count towards the bytes size of my write operation, which are also charged by MongoDB.
So if anyone has a better solution to this, I'm all ears.
According to this SO answer,
What you actually do inside of the document (push around an array, add a field) should not have any significant impact on the total cost of the operation
So, in your case, your array operations should not be causing a heavy impact on the total cost.
I have a question about creating JavaScript arrays. Here's what I want to do.
I have two arrays. Each array has object(s) in them.
The first array has exactly 5 objects, each with a key/value pair (id/name). This array will ALWAYS have 5 objects.
Here's what it looks like...
[
{
"id": 1,
"name": "AnalyticalAdmin"
},
{
"id": 2,
"name": "Analyst"
},
{
"id": 4,
"name": "AdminReviewer"
},
{
"id": 5,
"name": "SystemAdministrator"
},
{
"id": 6,
"name": "CaseworkSTRTechLeader"
}
]
The second array will have either...
no objects,
4 or less objects,
exactly 5 objects.
In the example below, the second array only has one of the 5 objects in the first array...
[
{
"id": 4,
"name": "AdminReviewer"
}
]
I need to create a third array that has exactly 5 boolean values that are determined by comparing the first two arrays.
For example, based on the first two arrays above, the third array would be...
[false, false, true, false, false]
The reason the third array would look like this is because "AdminReviewer" is the third object in the first array, so the third boolean value in the third array would be true (since it's a match).
But because the first, second, fourth, and fifth objects in the first array do not exist in the second array, their boolean equivalent in the third array would be false.
To accomplish this, I know I need to either do a compare function on the first two arrays to create the third array (of booleans) or I need to run a for loop on the first array, comparing it to the second array to create the third array (of booleans).
Can anyone help me with this?
This could be done as follows:
const filterStrings = filterArray.map(o => JSON.stringify(o));
const result = baseArray.map(o => filterStrings.includes(JSON.stringify(o)));
Please take a look at below runnable code and see how it works.
const baseArray = [
{
"id": 1,
"name": "AnalyticalAdmin"
},
{
"id": 2,
"name": "Analyst"
},
{
"id": 4,
"name": "AdminReviewer"
},
{
"id": 5,
"name": "SystemAdministrator"
},
{
"id": 6,
"name": "CaseworkSTRTechLeader"
}
];
const filterArray = [
{
"id": 4,
"name": "AdminReviewer"
}
];
const filterStrings = filterArray.map(o => JSON.stringify(o));
const result = baseArray.map(o => filterStrings.includes(JSON.stringify(o)));
console.log(result);
I have two arrays:
dataArray1 = [{
"id":1
"addressDetails": {55:1,56:20}
},
{
"id":2
"addressDetails": {55:30,56:10}
}
]
Above array contains addressDetails as object.
dataArray2= [{
"id":1
"addressDetails": [
{
"addressId": "55",
"city":"london",
"code":1
},
{
"addressId": "56",
"city":"paris",
"code":1
}
]
},
{
"id":2
"addressDetails": [
{
"addressId": "55",
"city":"london",
"code":0
},
{
"addressId": "56",
"city":"paris",
"code":0
}
]
}
]
This second array contains arrayDetails as array.
In both the arrays, id and addressId will be same. On the basis of both these id's I need to replace addressDetails object in dataArray1 by addressDetails array of dataArray2. In this replacement, I need to change value of "code" property of addressDetails array with the right hand side value(value on right side in addressDetailObject) for that particular id and addressId. For example, for Id "1" and addressId "55", in addressDetails object - "addressDetails": {55:1,56:10} value is "1", so I need to change value of "code" property in addressDetailsArrays with 1 and copy rest attritubtes as it is. How can I do that?
For this you can run
let result = array1.map((item) => {
//code to change item here
//find address value of array2 based on id and addressId
//replace the code with the address.code details you found above
});
What we are doing here is iterating over items of array1 and returning an updated value for each item.
I have a question about manipulating data in an associative array.
What I want to do
I want to verify if an order exists in sellingItems.
Background(why?)
I want to check if there is an order to return the number of products in stock as a response.
Question
I want to check if a specific data (order) exists in an associative array and calculate the inventory count.
public calculateStockQuantity(itemInstances) {
const stockQuantity = //We want to count the number of items in stock. In this case, we want it to be 2 (calculated based on whether the data exists in sellingItem.order or not).)
return stockQuantity;
}
Associative array of targets
//There are three itemInstances for one product because the number of products sold is three.
itemInstances =
[
{
"id": "1",
"sellingItem": [
{
"id": 1,
"price": 3000,
"orderedItem": [
{
"id": 1
"ordered_at": "2021-04-01 10:00:00"
}
]
}
]
},
{
"id": "2",
"sellingItem": [
{
"id": 2,
"price": 3000,
"orderedItem": []
}
]
},
{
"id": "2",
"sellingItem": [
{
"id": 2,
"price": 3000,
"orderedItem": []
}
]
}
]
Sorry for asking like a newbie.
Please check if this is something you are looking for, assuming if orderedItem array is empty then that sellingItem will be counted as in stock
let count = itemInstances.filter(({sellingItem : [{ orderedItem }]}) => orderedItem.length === 0).length;
console.log(count); //return 2 based on question data
Is it possible to remove elements from multiple subarrays inside of one big array? My structure looks something like this:
{
"_id": {
"$oid": ""
},
"users": [
{
"friends": [
"751573404103999569"
]
},
{
"friends": [
"220799458408005633"
]
}
]
}
I have a friend id and I need to remove it from all the "friends" arrays in the "users" array
You can do with the positional operator $[] as follow:
db.no_more_friends.update({ "users.friends":"the_friend_id" },{ $pull:{"users.$[].friends":"the_friend_id"}} ,{multi:true})
Just take in consideration that with {multi:true} it will perform the user id removal to all friends sub-arrays in all documents where "the_friend_id" is found