I am trying to remove an array element from a nested structure.
For example element with ID 21 needs to be removed from the document.
FOR doc in [
{
_key:1,
Lvl1:[
{ID:1, Lvl2:[{ID:10,Text:"A"},{ID:11,Text:"B"},{ID:12,Text:"C"}]},
{ID:2, Lvl2:[{ID:20,Text:"D"},{ID:21,Text:"E"},{ID:22,Text:"F"}]},
]
}]
return {_key:doc._key ,Lvl1:doc.Lvl1[*].Lvl2[* FILTER CURRENT.ID!=21]}
The fitler basically works, but the document structure is not preserved so I cannot perform an update on Lvl1 of the document.
Output
[
{
"_key": 1,
"Lvl1": [
[
{
"ID": 10,
"Text": "A"
},
{
"ID": 11,
"Text": "B"
},
{
"ID": 12,
"Text": "C"
}
],
[
{
"ID": 20,
"Text": "D"
},
{
"ID": 22,
"Text": "F"
}
]
]
}
Here is a solution:
FOR doc in [
{
_key:1,
Lvl1:[
{ID:1, Lvl2:[{ID:10,Text:"A"},{ID:11,Text:"B"},{ID:12,Text:"C"}]},
{ID:2, Lvl2:[{ID:20,Text:"D"},{ID:21,Text:"E"},{ID:22,Text:"F"}]},
]
}]
return {_key:doc._key ,Lvl1:(
FOR item IN doc.Lvl1
RETURN {ID: item.ID,Lvl2: item.Lvl2[* FILTER CURRENT.ID!=21]}
)}
Using the nested FOR works as a map operation and can give you more control over the output.
Related
I want to pull multiple objects from array.
Here is my sample collection:
Users
{
"_id": "wef324DGSshf",
"userTypes": [
{
"type": "students",
"users": [
{
"name": "John",
"age": 20
},
{
"name": "Mike",
"age": 20
},
{
"name": "Henry",
"age": 30
},
{
"name": "Henry",
"age": 40
}
]
}
]
}
I need to pull those objects where:
type: "students" and ages: [20,40]
So I have these 2 inputs: type & ages
Expected Response:
{
"_id": "wef324DGSshf",
"userTypes": [
{
"type": "students",
"users": [
{
"name": "Henry",
"age": 30
}
]
}
]
}
I have tried this query so far but it is not working:
Users.update({
"userTypes.type": "students",
"userTypes.users.age": {$in: [20, 40]},
},
{
$pull: {
"userTypes": {
"userTypes.users.$.age": {$in: [20, 40]}
}
}
});
Can anyone help me what I am doing wrong here?
Use an arrayFilters to specify the filtering for "type": "students" and normally perform $pull on age
db.collection.update({},
{
"$pull": {
"userTypes.$[ut].users": {
"age": {
$in: [
20,
40
]
}
}
}
},
{
arrayFilters: [
{
"ut.type": "students"
}
],
multi: true
})
Mongo Playground
Explanation: Check out the official doc about arrayFilters. You can think of the entries in arrayFilters as predicates. For a variable ut, it needs to have type: students. Let's go back to the $pull part. The predicate is applied to userTypes. That means for an entry in userTypes, ut, it needs to fit in the predicate of type: students. At the same time, we are $pulling the entries that age is in [20, 40].
my data structure is and products elements all tags in empty
I need to add a value to mongo db inner object with array element without looking at other value. Can some one advice to do this.
[
{
"item": "journal",
"id": 11,
"products": [
{
"id": 3,
"name": "p one",
"tags": []
}
]
},
{
"item": "notebook",
"id": 14,
"products": [
{
"id": 4010,
"name": "item-five",
"tags": []
}
]
}
]
and I want to add tag in products elements with match product id '4010', so the expected response should be like
[
{
"item": "journal",
"id": 11,
"products": [
{
"id": 3,
"name": "p one",
"tags": []
}
]
},
{
"item": "notebook",
"id": 14,
"products": [
{
"id": 4010,
"name": "item-five",
"tags": [
{
"id": 21,
"key": "tag-one",
"name": "tag-one",
}
]
}
]
}
]
You should look at arrayFilter option https://www.mongodb.com/docs/v6.0/reference/operator/update/positional-filtered/#update-all-documents-that-match-arrayfilters-in-an-array
Something like this might do the trick.
db.collection.updateMany(
{ },
{ $push: { "products.$[x].tags": {
"id": 21,
"key": "tag-one",
"name": "tag-one",
} } },
{ arrayFilters: [{ "x.id": 4010 }] }
);
I am unwinding a lookup joined by { preserveNullAndEmptyArrays: true } option to include documents whose sizes field is null, missing, or an empty array. But in my case, I need to join nested lookup and the output result is not as I expected.
Specifically, I am being to set a new buyer field by the $set operator from lookup but if this lookup is null or empty array it will return [ { } ] and I don't want that. How can I replace [ { } ] with empty array?
The result I got:
[
{
"_id": ObjectId("5a934e000102030405000000"),
"buyers": [
{
"_id": ObjectId("5a934e000102030405000003"),
"buyer": {
"_id": ObjectId("5a934e000102030405000004"),
"display_name": "Phineas",
"user_id": "123"
},
"post_id": 1,
"user_id": "123"
}
],
"content": "content book 1",
"title": "title book 1"
},
{
"_id": ObjectId("5a934e000102030405000002"),
"buyers": [
{}
],
"content": "content book 3",
"title": "title book 3"
},
{
"_id": ObjectId("5a934e000102030405000001"),
"buyers": [
{}
],
"content": "content book 2",
"title": "title book 2"
}
]
The result that I expected:
[
{
"_id": ObjectId("5a934e000102030405000000"),
"buyers": [
{
"_id": ObjectId("5a934e000102030405000003"),
"buyer": {
"_id": ObjectId("5a934e000102030405000004"),
"display_name": "Phineas",
"user_id": "123"
},
"post_id": 1,
"user_id": "123"
}
],
"content": "content book 1",
"title": "title book 1"
},
{
"_id": ObjectId("5a934e000102030405000002"),
"buyers": [],
"content": "content book 3",
"title": "title book 3"
},
{
"_id": ObjectId("5a934e000102030405000001"),
"buyers": [],
"content": "content book 2",
"title": "title book 2"
}
]
Now you can see my code in the Mongo playground link:
https://mongoplayground.net/p/qiC7FySejxF
Comparing your actual output and MongoDB Playground link, I believe that you miss out the $unset stage.
{
$unset: "buyers.buyers"
}
While after the $unset stage, you can add $set stage to update the buyers field by filtering the document which is not empty document via $filter.
{
$set: {
buyers: {
$filter: {
input: "$buyers",
cond: {
$ne: [
"$$this",
{}
]
}
}
}
}
}
Demo # Mongo Playground
I have a problem to writing a mongodb query to nested updating an array of objects.
My current document in the collection is like this:
{
"_id": 1,
"data": {
"arr_1": [
{
"inner_arr_1": [
{
"aid": "111",
"ans": "def"
},
{
"aid": "222",
"ans": "def"
},
],
"inner_arr_2": [
{
"aid": "333",
"ans": "def"
},
{
"aid": "444",
"ans": "def"
},
],
"inner_arr_3": [
{
"aid": "555",
"ans": "def"
},
{
"aid": "666",
"ans": "def"
},
]
},
]
},
"name": "John"
}
I want to write an API endpint by express in nodejs to nested update this document.
The post body of the endpoint is like:
req.body = {
"_id": 1,
"data": {
"arr_1": [
{
"inner_arr_1": [
{
"aid": "111",
"ans": "new val"
}
],
"inner_arr_3": [
{
"aid": "666",
"ans": "new val"
}
]
},
]
}
}
Anyone can help me to write a query to solve this problem?
Thank you.
Apollo query has the wrong data from cache in my react app.
If I set query's fetchPolicy to 'network-only', everything work properly.
So I think it is a cache problem.
I have been working hard trying to solve the problem and see articles about apollo cache, but I still can't solve the problem.
Here are my results after querying:
parameter memberId is null (result is correct)
[
{
"id": 87,
"totalQuantity": 12,
"Orders": [
{
"id": 1,
"quantity": 11,
"Member": {
"id": 1,
"name": "A"
}
},
{
"id": 28,
"quantity": 1,
"Member": {
"id": 9,
"name": "B"
}
}
]
},
{
"id": 88,
"totalQuantity": 1,
"Orders": [
{
"id": 2,
"quantity": 1,
"Member": {
"id": 1,
"name": "A"
}
}
]
}
]
parameter memberId is 9 (result is correct)
[
{
"id": 87,
"totalQuantity": 1,
"Orders": [
{
"id": 28,
"quantity": 1,
"Member": {
"id": 9,
"name": "B"
}
}
]
}
]
parameter memberId is 1 (result is correct)
[
{
"id": 87,
"totalQuantity": 11,
"Orders": [
{
"id": 1,
"quantity": 11,
"Member": {
"id": 1,
"name": "A"
}
}
]
},
{
"id": 88,
"totalQuantity": 1,
"Orders": [
{
"id": 2,
"quantity": 1,
"Member": {
"id": 1,
"name": "A"
}
}
]
}
]
but when I back to parameter is null the result is wrong
[
{
"id": 87,
"totalQuantity": 11,
"Orders": [
{
"id": 1,
"quantity": 11,
"Member": {
"id": 1,
"name": "A"
}
}
]
},
{
"id": 88,
"totalQuantity": 1,
"Orders": [
{
"id": 2,
"quantity": 1,
"Member": {
"id": 1,
"name": "A"
}
}
]
}
]
Member B (id = 9) is disappear..
and I back to parameter is 9 (result is wrong)
[
{
"id": 87,
"totalQuantity": 11,
"Orders": [
{
"id": 1,
"quantity": 11,
"Member": {
"id": 1,
"name": "A"
}
}
]
}
]
I get the Member A's data instead of Member B
Can someone help me? Thanks
My client configuration (cache is InMemoryCache)
const client = new ApolloClient({
link: ApolloLink.from([
httpLink,
]),
cache,
dataIdFromObject: o => ${o.id}${o.__typename},
});
I use queryHook to wrap my component
const queryHook = graphql(FETCH_ORDER_GROUP_SHIPMENT_LIST, {
options: ownProps => ({
variables: {
memberId: ownProps.options.memberId || null,
},
}),
props: ({
data: {
orderGroupShipmentList,
},
}) => ({
orderGroupShipmentList: orderGroupShipmentList || [],
});
Also I use Query tag(other data) to wrap my content
and its parameter is memberId as well.
the structure like this
<Query
variables={{ memberId: options.memberId || null }}
query={FETCH_MEMBER_LIST_QUERY}>
content that use orderGroupShipmentList and memberList
</Query>
I don't know if this is specific enough
Let me know if this is not specific enough
Thanks
2019-09-16
For those who facing the same problem:
https://kamranicus.com/posts/2018-03-06-graphql-apollo-object-caching
You need to have different ids for that type on the returned results for your query. For example, you have different results for id 87 based on memberId, so the cache will be overwritten by your second query and since apollo does not refetch queries already made by default it will continue to look at the overwritten result.
#Anymore - can we see you FETCH_MEMBER_LIST_QUERY code? Are you fetching id's for all the data? Without the ids it won't be able to match relations.
Have you tried using Apollo Client DevTools - they will let you easily view the contents of the cache. It can be found on GitHub here and the Chrome Webstore here
Using this you will be able to see if the item is being cached correctly.