Insert Array of Objects using jsonb_array_elements - postgresql

I have an array of json Objects in following format:
[
{
product: {
id: 24,
raisedby: 'abc#testcom'
}
},
{
product: {
id: 12,
raisedby: 'xyz#testcom'
}
},
{
product: {
id: 9,
raisedby: 'abcde#testcom'
}
}
]
I am trying to build a Postgres Insert Statement as follows but it does not work. Any help appreciated
insert into public.redeem_request(redeem_product_id, redeem_raisedby)
select (e->> 'product'->> 'id')::int,
e->>'product' ->> 'raisedby'
from jsonb_array_elements($1) as t(e)
returning *

Related

Can't remove nested elements from object

I have this table here:
Table: User
{
id: 1,
name: 'user 1',
superPowers: [
{
id: 1,
map: {
status: 'offline'
}
},
{
id: 2,
map: {
status: 'online'
}
},
{
id: 3,
map: {
status: 'online'
}
}
]
}
And I would like to return an object with the user information only containing superpowers that have the map in the online mode. I built this query:
await getRepository(User).createQueryBuilder('user')
.leftJoinAndSelect('user.superPowers', 'superPowers')
.leftJoinAndSelect('superPowers.map', 'map')
.where('map.status = status', {status: EnumStatusMap.ONLINE})
.andWhere('user.id = :id', {id: 1}).getOne();
But this query returns me all the supowerPowers, including the ones where the map status is offline
What am I doing wrong?

How to make and requests in mongodb queries

I've worked on this for about an hour now and I can't figure anything out that works so sorry if this is obvious.
I want my query to only return results where every result matches, but right now it returns a result if at least one match is found.
My document looks like this...
{
country: 'Great Britain',
data: [
{
school: 'King Alberts',
staff: [
{
name: 'John',
age: 37,
position: 'Head Teacher'
},
{
name: 'Grace',
age: 63,
position: 'Retired'
},
{
name: 'Bob',
age: 25,
position: 'Receptionist'
}
]
},
{
school: 'St Johns',
staff: [
{
name: 'Alex',
age: 22,
position: 'Head of Drama'
},
{
name: 'Grace',
age: 51,
position: 'English Teacher'
},
{
name: 'Jack',
age: 33,
position: 'Receptionist'
}
]
},
// ... more schools
]
}
The query I'm currently making looks like...
{ 'data.staff.name': { $in: names } }
and the 'names' array that is being provided looks like ['Bob', 'Grace', 'John', 'Will', 'Tom']. Currently both schools are being returned when I make this query, I think it's because the 'names' array contains 'Grace' which is a name present at both schools and so the document it matching. Does anyone know if there's a query I could make so mongodb only returns the school object if every name in the 'names' array is a member of staff at the school?
You need to use the aggregation pipeline for this, after matching the document we'll just filter out the none matching arrays, like so:
db.collection.aggregate([
{
$match: {
"data.staff.name": {
$in: names
}
}
},
{
$addFields: {
data: {
$filter: {
input: "$data",
cond: {
$eq: [
{
$size: {
"$setIntersection": [
"$$this.staff.name",
names
]
}
},
{
$size: "$$this.staff"
}
]
}
}
}
}
}
])
Mongo Playground

MongoDB query - unwind and match preserving null OR different value/ add a new field based on a condition

If a have a following structure :
{
_id: 1,
name: 'a',
info: []
},
{
_id: 2,
name: 'b',
info: [
{
infoID: 100,
infoData: 'my info'
}
]
},
{
_id: 3,
name: 'c',
info: [
{
infoID: 200,
infoData: 'some info 200'
},
{
infoID: 300,
infoData: 'some info 300'
}
]
}
I need to query in such a way to obtain the documents where infoID is 100 showing the infoData, or nothing if info is empty, or contains subdocuments with infoID different from 100.
That is, I would want the following output:
{
_id: 1,
name: 'a',
infoData100: null
},
{
_id: 2,
name: 'b',
infoData100: 'my info'
},
{
_id: 3,
name: 'c',
infoData100: null
}
If I $unwind by info and $match by infoID: 100, I lose records 1 and 3.
Thanks for your responses.
Try below query :
Query :
db.collection.aggregate([
/** Adding a new field or you can use $project instead of addFields */
{
$addFields: {
infoData100: {
$cond: [
{
$in: [100, "$info.infoID"] // Check if any of objects 'info.infoID' has value 100
},
{
// If any of those has get that object & get infoData & assign it to 'infoData100' field
$let: {
vars: {
data: {
$arrayElemAt: [
{
$filter: {
input: "$info",
cond: { $eq: ["$$this.infoID", 100] }
}
},
0
]
}
},
in: "$$data.infoData"
}
},
null // If none has return NULL
]
}
}
}
]);
Test : MongoDB-Playground

How to filter objects with subquery?

Usking shiki/kaiseki to interact with the Parse REST api. I'm trying to get all As that do not have a related B for a user.
I know I can get Bs for a user:
parseClient.getObjects('B', {
where: {
user: {
__type: "Pointer",
objectId: "id here",
className: "_User"
}
},
keys: 'a'
}, callback)
And then pluck object ids to get the bad A ids.
aIds = [ Bs ].map(function (b) {
return b.a.objectId
})
And then query for As negative matching the id.
parseClient.getObjects('A', {
where: {
objectId: { $nin: aIds }
}
}, callback)
But a user can have more B's than the query limit of 200. How can I rewrite it to use a subquery?
$dontSelect
Nested key param doesn't work, which makes something like this fall flat.
parseClient.getObjects('A', {
where: {
objectId: {
$dontSelect: {
query: {
className: 'B',
where: { user query },
},
key: 'a.objectId
}
}
}
}, callback)
// { code: 105, error: 'invalid field name: ' }
$notInQuery
There doesn't seem to be a way to put $notInQuery in the root of the where or to reference the current object.
parseClient.getObjects('A', {
where: {
$notInQuery: {
className: 'B',
where: { user query },
key: 'a'
}
}
}, callback)
// { code: 102, error: 'Invalid key $notInQuery for find' }
Help!
It is a limitation of the Parse model, and the only way I have found around it is to adjust your schema accordingly.
One way you could do it is with a relation on A that contains all related User pointers and then do a $ne against the relation field:
where: {
'relationColumn' : {
'$ne': {
'__type': 'Pointer',
'className': '_User',
'objectId': 'user b id here'
}
}
}

Move elements from $pull to another array

I have many documents in the same collection that look like this:
{
"_id": ObjectId("4d525ab2924f0000000022ad"),
"array": [
{ id: 1, other: 23 },
{ id: 1, other: 21 },
{ id: 0, other: 235 },
{ id: 1, other: 765 }
],
"zeroes": []
}
and I want them to look like this:
{
"_id": ObjectId("4d525ab2924f0000000022ad"),
"array": [
{ id: 1, other: 23 },
{ id: 1, other: 21 },
{ id: 1, other: 765 }
],
"zeroes": [
{ id: 0, other: 235 }
]
}
Basically, I want to be able to pull some elements in an array, and push it to another array. I know I can use $pull to conditionally remove elements from an array, but is it possible to relocate these pulled elements?
Not really. You can use cursor for operation like this.
db.foo.find({}).forEach(function(doc) {
doc.zeros = doc.array.filter(function(x) { return x.id == 0 });
doc.array = doc.array.filter(function(x) { return x.id != 0 });
db.foo.save(doc)};
)