Not picking Index - when querying Object -> array -> Object in N1QL - nosql

Index not picking when using N1QL to match all the customers belonging to a country
Note : the bucket has around 10 lack records, the document is fetching after 50 seconds,
query
select * from `user-prof` WHERE ANY item IN devices.location SATISFIES item.country IN ["US"]
index
CREATE INDEX id_userProfile ON `user-prof` ( ALL ARRAY v.country FOR v IN devices.location END )
Document
[
{
"customers": {
"devices": {
"user": "u1",
"custid": "14CE5534CCE",
"token": "4D5BE85896833148D696A1397C",
"guest": {
"lastActive": null,
"searches": [
]
},
"latt": "6655059908",
"locale": "en-US",
"location": [
{
"city": "Afc",
"country": "IN"
},
{
"city": "Newyork",
"country": "US"
},
{
"city": null,
"country": null
}
],
"long": "4.21787927806",
"notify": {
"Stats": false
},
"tier": null,
"tmz": "EU",
"version": "0.1"
}
}
},
{
"customers": {
"devices": {
"user": "u2",
"custid": "64CE5534CC1E",
"token": "6D5BE85896833148D696A1397C",
"guest": {
"lastActive": null,
"searches": [
]
},
"latt": "6655059908",
"locale": "en-US",
"location": [
{
"city": "Texas",
"country": "US"
},
{
"city": null,
"country": null
}
],
"long": "4.21787927806",
"notify": {
"Stats": false
},
"tier": null,
"tmz": "EU",
"version": "0.1"
}
}
}

You are using Pre 4.6.2 The variable in the ANY clause needs to be same as the variable in the CREATE INDEX (i.e item ,v )
https://developer.couchbase.com/documentation/server/current/n1ql/n1ql-language-reference/indexing-arrays.html

Related

Query complex JSON in Postgres

I have a json column named "Payload" with a complex json structure as below-
{
"Number": "",
"Status": "",
"Parties": [
{
"BeCode": "SHANGMAG",
"PartyCode": "CNSHANGMAGVDR",
},
{
"BeCode": "FREEMAN",
"PartyCode": "CNFREEMANVDR",
}
],
"ContactName": "test",
"Type": "",
"Legs": [
{
"Name": "",
"ELocation": {
"City": "Enns",
"State": null,
"Country": "Austria",
},
"Socation": {
"City": "Buenos Aires",
"State": null,
"Country": "Argentina",
},
"Transport": 1
},
{
"Name": "84nbt",
"ELocation": {
"City": "Linz",
"State": null,
"Country": "Austria",
},
"SLocation": {
"City": "Enns",
"State": null,
"Country": "Austria",
},
"Transport": 2
}
]
"Bookings": [
{
"BookingNo": "",
"Status": "",
"Id": ""
}
]
}
Now I need to query all the rows where SLocation is equal to ELocation.
I was able to get the "Legs" part row vise using following query -
select payload->'Legs'
from public.shipping_instruction
However, If I dig deep into the json to get the SLocation and ELocation, the query doesnt exceute.
I am looking for something like the one below-
select payload->'Legs'
from public.shipping_instruction where
payload->'Legs'->'ELocation'->'City' =
payload->'Legs'->'SLocation'->'City'
But then here the Legs have multiple SLocation and ELocation how do I handle it?
select "Number",
x."Status" as Status,
"BeCode",
"PartyCode",
"ContactName",
"Type",
"Name",
"Transport",
e_city,
e_state,
e_country,
s_city,
s_state,
s_country,
"BookingNo",
b."Status" as BookingStatus,
"Id"
from jsonb_to_record('{
"Number": "",
"Status": "",
"Parties": [
{
"BeCode": "SHANGMAG",
"PartyCode": "CNSHANGMAGVDR"
},
{
"BeCode": "FREEMAN",
"PartyCode": "CNFREEMANVDR"
}
],
"ContactName": "test",
"Type": "",
"Legs": [
{
"Name": "",
"ELocation": {
"City": "Enns",
"State": null,
"Country": "Austria"
},
"SLocation": {
"City": "Buenos Aires",
"State": null,
"Country": "Argentina"
},
"Transport": 1
},
{
"Name": "84nbtMatch",
"ELocation": {
"City": "Linz",
"State": null,
"Country": "Austria"
},
"SLocation": {
"City": "Linz",
"State": null,
"Country": "Austria"
},
"Transport": 2
},
{
"Name": "84nbt",
"ELocation": {
"City": "Linz",
"State": null,
"Country": "Austria"
},
"SLocation": {
"City": "Enns",
"State": null,
"Country": "Austria"
},
"Transport": 3
}
],
"Bookings": [
{
"BookingNo": "bn",
"Status": "bs",
"Id": "bid"
}
]
}'::jsonb) as x("Number" text,
"Status" text,
"Parties" jsonb,
"ContactName" text,
"Type" text,
"Legs" jsonb,
"Bookings" jsonb),
lateral jsonb_to_recordset(x."Parties") as p("BeCode" text, "PartyCode" text),
lateral jsonb_to_recordset(x."Legs") as l("Name" text, "Transport" int, "ELocation" jsonb, "SLocation" jsonb),
lateral (select l."ELocation" ->> 'City' as e_city,
l."ELocation" ->> 'State' as e_state,
l."ELocation" ->> 'Country' as e_country,
l."SLocation" ->> 'City' as s_city,
l."SLocation" ->> 'State' as s_state,
l."SLocation" ->> 'Country' as s_country
) loc,
lateral jsonb_to_recordset(x."Bookings") as b("BookingNo" text, "Status" text, "Id" text)
where coalesce(e_city, '') = coalesce(s_city, '')
and coalesce(e_state, '') = coalesce(s_state, '')
and coalesce(e_country, '') = coalesce(s_country, '');

how to update the first object in the array of quarterFinals that matches some mongoDB condition?

I have the document below and I need to iterate through the quarterFinals array and update the first null address property I find to '123'
{
"data": {
"createTournament": {
"_id": "613122d0c7befdeef3b0b571",
"title": "Jogo de truco",
"description": "",
"location": "Batalha na rua",
"type": "Battle",
"players": [],
"status": "PENDING",
"size": 8,
"entryFee": 1,
"prizePool": 20,
"currency": "USD",
"startDate": "2021-09-01",
"endDate": "2021-09-01",
"rounds": {
"quarterFinals": [{
"id": "9fb6f9ca-c06a-4972-b140-0f2425a90707",
"arena": "",
"firstParticipant": {
"address": null,
"battlesWon": 0
},
"secondParticipant": {
"address": null,
"battlesWon": 0
}
}]
}
}
}
}
One way of doing this is
exports.updateData = async (tournamentID,address)=>{
return await db_collection.updateOne({id:tournamentId,rounds:{$elemMatch:{quarterfinals.address:null}}},{$push:{address:address});
};

How to get length of sub array in mongo query

Below is the sample data:
db.infos.find()
{
"groupId": "1111",
"customerId": "A100",
"tracks": [{
"trackId": "234",
"infos": [{
"location": {
"address": "street1",
"city": "test",
"country": "US"
}
},
{
"location": {
"address": "street2",
"city": "test",
"country": "US"
}
},
{
"location": {
"address": "street3",
"city": "test",
"country": "US"
}
}
]
}]
}
{
"groupId": "2222",
"customerId": "A100",
"tracks": [{
"trackId": "345",
"infos": [{
"location": {
"address": "street4",
"city": "test",
"country": "US"
}
},
{
"location": {
"address": "street5",
"city": "test",
"country": "US"
}
},
{
"location": {
"address": "street5",
"city": "test",
"country": "US"
}
}
]
}]
}
{
"groupId": "2222",
"customerId": "A100",
"tracks": [{
"trackId": "666",
"infos": [{
"location": {
"address": "street4",
"city": "test",
"country": "US"
}
},
{
"location": {
"address": "street5",
"city": "test",
"country": "US"
}
},
{
"location": {
"address": "street5",
"city": "test",
"country": "US"
}
}
]
}]
}
We need a query to get the length of "infos" sub array at groupId level. In the above sample data, we need the below output:
1111, 3
2222, 6
Tried below, but its not working:
db.infos.aggregate([{"$project": {"groupId": "$groupId", "samples": "$tracks.infos"}}, {"$group": {"_id": "$groupId", "samples": {"$push": "$samples"}}}, {"$project": {"_id": 1, "samples": {"$size": "$samples"}}}], { "allowDiskUse": true });
Also with large amount of data, above query is throwing an ExceededMemoryLimit exception:
2021-07-10T07:20:14.415+0000 E QUERY [js] Error: command failed: {
"ok" : 0,
"errmsg" : "$push used too much memory and cannot spill to disk. Memory limit: 104857600 bytes",
"code" : 146,
"codeName" : "ExceededMemoryLimit"
} : aggregate failed :
_getErrorWithCode#src/mongo/shell/utils.js:25:13
doassert#src/mongo/shell/assert.js:18:14
_assertCommandWorked#src/mongo/shell/assert.js:580:17
assert.commandWorked#src/mongo/shell/assert.js:673:16
DB.prototype._runAggregate#src/mongo/shell/db.js:260:9
DBCollection.prototype.aggregate#src/mongo/shell/collection.js:1074:12
#(shell):1:1
This should work with unwind:
db.collection.aggregate([
{
$unwind: "$tracks"
},
{
$group: {
"_id": "$groupId",
"count": {
"$sum": {
"$size": "$tracks.infos"
}
}
}
}
])
Even if your tracks array has more than one object this will add them up. Playground

MongoDb extract array

I have a mongodb which I want to extract some specific data.
Here is my json:
{
"jobs" : [
{
"id": 554523,
"code": "1256-554523",
"name": "Banco de Talentos",
"status": "published",
"type": "vacancy_type_effective",
"publicationType": "external",
"numVacancies": 1,
"departmentId": 108141,
"departmentName": "FUTURAS OPORTUNIDADES",
"roleId": 169970,
"roleName": "BANCO DE TALENTOS",
"createdAt": "2020-10-30T12:23:48.572Z",
"updatedAt": "2020-12-30T23:21:30.403Z",
"branchId": null,
"branchName": null
},
{
"id": 616834,
"code": "1256-616834",
"name": "YYYYYY (o) YYYYY",
"status": "frozen",
"type": "vacancy_type_effective",
"publicationType": "external",
"numVacancies": 1,
"departmentId": 109190,
"departmentName": "TESTE TESTE",
"roleId": 165712,
"roleName": "SL - TESTE PL",
"createdAt": "2020-12-16T14:17:36.187Z",
"updatedAt": "2021-01-29T17:08:43.613Z",
"branchId": 120448,
"branchName": "TESTE TESTE1"
}
],
"application": [
{
"id": 50707344,
"score": 40.251965332031254,
"partnerName": "indeed",
"endedAt": null,
"createdAt": "2020-12-21T11:21:30.587Z",
"updatedAt": "2021-02-18T22:02:35.866Z",
"tags": {},
"candidate": {
"birthdate": "1986-04-04",
"id": 578615,
"name": "TESTE",
"lastName": "TESTE TESTE",
"email": "teste#teste.com.br",
"identificationDocument": "34356792807",
"countryOfOrigin": "BR",
"linkedinProfileUrl": "teste",
"gender": "female",
"mobileNumber": "+5511972319799",
"phoneNumber": "(11)2463-2039"
},
"job": {
"id": 619713,
"name": "XXXXde XXXX Pleno"
},
"manualCandidate": null,
"currentStep": {
"id": 3527370,
"name": "Cadastro",
"status": "done"
}
},
{
"id": 50707915,
"score": 3.75547943115234E+1,
"partnerName": "indeed",
"endedAt": null,
"createdAt": "2020-12-21T11:31:31.877Z",
"updatedAt": "2021-02-18T14:07:06.605Z",
"tags": {},
"candidate": {
"birthdate": "1971-10-02",
"id": 919358,
"name": "TESTE TESTE",
"lastName": "SILVA",
"email": "teste.teste#teste.com",
"identificationDocument": "3232323232",
"countryOfOrigin": "BR",
"linkedinProfileUrl": "teste/",
"gender": "female",
"mobileNumber": "11 94021- 5521",
"phoneNumber": "+5511995685247"
},
"job": {
"id": 619713,
"name": "Analista de XXXXX Pleno"
},
"manualCandidate": null,
"currentStep": {
"id": 3527370,
"name": "Cadastro",
"status": "done"
}
}
]
}
My question is: How can I extract only the array objects in jobs and application separately? Anyone knows the code in Mongodb for do this?
I need do this task for after I can insert the extract separated data in different collections.
Thanks a lot.
Unfortunately there is no real "good" way of doing this. Here is an example of how I would do it by using $facet and other operators to manipulate the structure
db.collection.aggregate([
{
$match: {
/** your query*/
}
},
{
$facet: {
jobs: [
{
$unwind: "$jobs"
},
{
$replaceRoot: {
newRoot: "$jobs"
}
}
],
applications: [
{
$unwind: "$application"
},
{
$replaceRoot: {
newRoot: "$application"
}
}
]
}
},
{
$addFields: {
"merged": {
"$concatArrays": [
"$jobs",
"$applications"
]
}
}
},
{
$unwind: "$merged"
},
{
"$replaceRoot": {
"newRoot": "$merged"
}
}
])
Mongo Playground
I would personally just do it in code after you fetched the document.

Find specific field in array by last date and updating it

I have the document below, and I want to update in exams, the last exam with status "started" (according to date), I need to add to "done" another number
{
"_id": ObjectID("5d2a371cec7eaf00119df614"),
"firstname": "Laura",
"lastname": "Warriner",
"image": "2019-07-14t05:25:23.352z_13.jpg",
"exams": [
{
"examId": "Ba6apmRmz",
"name": "general",
"language": "es",
"version": 2,
"testId": "2000",
"status": [
{
"status": "created",
"date": ISODate("2019-09-08T11:49:42.124Z")
},
{
"status": "started",
"date": ISODate("2019-09-08T11:55:09.873Z"),
"done": [1]
},
{
"status": "started",
"date": ISODate("2019-09-09T12:01:57.886Z"),
"done": [2,3]
},
{
"status": "completed",
"date": ISODate("2019-09-09T12:01:57.886Z")
}
]
}
]
}
Thanks in advance