Extract elements from JSON array and return them as concatenated string - postgresql

A PostgreSQL 10 table contains JSON data like (here an SQL Fiddle):
[
{
"col": 7,
"row": 12,
"value": 3,
"letter": "A"
},
{
"col": 8,
"row": 12,
"value": 10,
"letter": "B"
},
{
"col": 9,
"row": 12,
"value": 1,
"letter": "C"
},
{
"col": 10,
"row": 12,
"value": 2,
"letter": "D"
}
]
How to extract only the "letter" values and concatenate them to a string like
ABCD
I suppose at the end I should use the ARRAY_TO_STRING function, but which JSON function to use for extracting the "letter" values to an array?
UPDATE:
Got a tip at the very helpful PostgreSQL mailing list too:
SELECT string_agg(x->>'letter','') FROM json_array_elements(
'[{"col": 7, "row": 12, "value": 3, "letter": "A"}, {"col": 8, "row": 12, "value": 10, "letter": "B"}, {"col": 9, "row": 12, "value": 1, "letter": "C"}, {"col": 10, "row": 12, "value": 2, "letter": "D"}]'::json
) x;

Use jsonb_array_elements() and string_agg():
with my_table(json_data) as (
values(
'[
{
"col": 7,
"row": 12,
"value": 3,
"letter": "A"
},
{
"col": 8,
"row": 12,
"value": 10,
"letter": "B"
},
{
"col": 9,
"row": 12,
"value": 1,
"letter": "C"
},
{
"col": 10,
"row": 12,
"value": 2,
"letter": "D"
}
]'::jsonb)
)
select string_agg(value->>'letter', '')
from my_table
cross join lateral jsonb_array_elements(json_data)
string_agg
------------
ABCD
(1 row)

Related

How to insert data on last item of an inner array in MongoDB

I am trying to insert data in the last element of an array in MongoDB. insert in the first element works using the 0 operator, but I'm confused about how to insert in the last element. To explain it, consider the following data:
[
{
"_id": "1",
"company": "turivius",
"forms": [
{
"current_version": 1,
"history": [
{
"content": [],
"layout": [],
"responses": [
{
"client_id": 100,
"response_date": datetime(2022, 5, 17, 3, 0),
"values": [
{
"field_id": 0,
"primeiro user": "primeiro form, resposta 1",
},
{
"field_id": 1,
"value": "aaa",
},
],
},
{
"client_id": 100,
"response_date": datetime(2022, 5, 17, 3, 0),
"values": [
{
"field_id": 0,
"primeiro user": "primeiro form, resposta 2",
},
{
"field_id": 1,
"value": "bbb",
},
],
},
],
"version": 0,
},
{
"content": [],
"layout": [],
"responses": [
{
"client_id": 100,
"response_date": datetime(2022, 5, 17, 3, 0),
"values": [
{
"field_id": 0,
"primeiro user": "primeiro form, resposta 1 v1",
},
{
"field_id": 1,
"value": "aaa",
},
],
}
],
"version": 1,
},
],
"id": "33b66684-24a9-4a45-a12f-27a330152ac8",
"is_active": True,
},
{
"current_version": 0,
"history": [],
"id": "fa2eb9a1-c7c4-4b64-b682-7f51658bc4ab",
"is_active": False,
},
],
"user_id": "1",
},
{
"_id": "2",
"company": "turivius",
"forms": [
{
"current_version": 0,
"history": [],
"id": "565656",
"is_active": True,
},
],
"user_id": "9999",
},
]
I want to insert data in the document with user_id = 1, form.id = 33b66684-24a9-4a45-a12f-27a330152ac8 and in the history array where the version = 1 I want to insert a new response:
{
"client_id": 100,
"response_date": datetime(2022, 5, 17, 3, 0),
"values": [
{
"field_id": 0,
"test": "test",
},
{
"field_id": 1,
"test2": "test3",
},
],
}
The history with version 1 is the last element, if I wanted insert in the first element the following code would works:
find_one_and_update(
{"$and": [{"user_id": "1"}, {"forms.id": '33b66684-24a9-4a45-a12f-27a330152ac8'}]},
{
"$push": {"forms.$.history.0.responses": data_here},
},
return_document=ReturnDocument.AFTER,
)
Is there anyway to do it that way or I need a more complex query to do it?
You want to add a new document to the responses array when those conditions are true:
{
user_id: '1',
'forms.id': '33b66684-24a9-4a45-a12f-27a330152ac8',
'forms.history.version': 1
}
forms is an array, so you want to update the array element that matches the condition, so you can use the $[identifier] operator. Inside the array of forms, you only want to update the history with a specific version, so you need to use the $[identifier] operator multiple times, the field you want to update would be like this:
forms.$[f].history.$[h].responses
f is the identifier of each elements in forms that matches the condition and h the elements of the history array that match the other condition. An arrayFilters object is used to define the conditions.
The complete query could be like this:
db.collection.update({
user_id: "1",
'forms.id': '33b66684-24a9-4a45-a12f-27a330152ac8',
'forms.history.version': 1
},
{
$push: {
'forms.$[f].history.$[h].responses': {
"client_id": 100,
"response_date": "datetime(2022, 5, 17, 3, 0)",
"values": [
{
"field_id": 0,
"test": "test",
},
{
"field_id": 1,
"test2": "test3",
},
],
}
}
},
{
arrayFilters: [
{
'h.version': 1
},
{
'f.id': '33b66684-24a9-4a45-a12f-27a330152ac8'
}
]
})
Working example at MongoDB playground

Flatten mongo db field

How can I flatten "Behavior" field so it becomes part of the document root ? I have tried with $project and $unwind functions but that ones did not seem to help me
I have json data like this:
"breed": "Akita",
"origin": "Japan",
"url": "https://en.wikipedia.org/wiki/Akita_(dog)",
"img": "some img url",
"WikiDescr": [
{
"contenido": "Content"
}
],
"Behavior": [
{
"good_with_children": 3,
"good_with_other_dogs": 1,
"shedding": 3,
"grooming": 3,
"drooling": 1,
"coat_length": 1,
"good_with_strangers": 2,
"playfulness": 3,
"protectiveness": 5,
"trainability": 3,
"energy": 4,
"barking": 2,
"min_life_expectancy": 10,
"max_life_expectancy": 14,
"max_height_male": 28,
"max_height_female": 28,
"max_weight_male": 130,
"max_weight_female": 100,
"min_height_male": 26,
"min_height_female": 26,
"min_weight_male": 100,
"min_weight_female": 70
}
and my desired output would be like this:
"breed": "Akita",
"origin": "Japan",
"url": "https://en.wikipedia.org/wiki/Akita_(dog)",
"img": "some img url",
"good_with_children": 3,
"good_with_other_dogs": 1,
"shedding": 3,
"grooming": 3,
"drooling": 1,
"coat_length": 1,
"good_with_strangers": 2,
"playfulness": 3,
"protectiveness": 5,
"trainability": 3,
"energy": 4,
"barking": 2,
"min_life_expectancy": 10,
"max_life_expectancy": 14,
"max_height_male": 28,
"max_height_female": 28,
"max_weight_male": 130,
"max_weight_female": 100,
"min_height_male": 26,
"min_height_female": 26,
"min_weight_male": 100,
"min_weight_female": 70
},
"WikiDescr": [
{
"contenido": "content"
}
],
I have tried this but it does not happen anything:
{ $unwind: "$Behavior" },
{ $replaceRoot: { newRoot: { $mergeObjects: ["$Behavior", "$$ROOT"] } } },
Any help would be appreciated since I am stuck with this trivial question

Very Complex Json with same field name

My colleague is response for backend development, this is one of example of the API response.
I want to know that how can I separate it to the map?
And There have same name, I am very difficult to handle it. JSON to Dart generated code also will have error case by same name.
Is there have any other solution to handle this Json?
{
"formId": 1,
"formTypeId": 2,
"formTemplateId": 1,
"version": 1,
"history": "N",
"refNum": "AGQ/T01/01/A1/QA2/0001",
"dateOfAcceptance": "2020/12/16 14:54:01",
"dateOfReacceptance": "2020/12/16 14:54:01",
"blockId": 242,
"floorId": 1,
"flatId": 98,
"isPublic": "N",
"locationId": 1,
"fromFloorId": 1,
"toFloorId": 2,
"elevationId": 1,
"isNextVendor": "Y",
"isMultipleVendor": "N",
"formStatusId": 1,
"checkResults": 1,
"submissionDate": "2020/12/16 14:54:01",
"submittedBy": "ADMINISTRATOR",
"siteId": "YLTL",
"formDetails": [
{
"formDetailsId": 1,
"formId": 1,
"title": "A. 驗收項目",
"checkType": 1,
"required": "Y",
"parentId": 0,
"orderNum": 1,
"formDetailsOptions": [],
"fromDetails": [
{
"formDetailsId": 3,
"formId": 1,
"title": "Title group",
"checkType": 2,
"required": "Y",
"parentId": 1,
"orderNum": 1,
"formDetailsOptions": [],
"fromDetails": [
{
"formDetailsId": 4,
"formId": 1,
"title": "門編號:",
"checkType": 5,
"required": "Y",
"parentId": 3,
"orderNum": 1,
"answerVal": "A001",
"formDetailsOptions": []
},
{
"formDetailsId": 5,
"formId": 1,
"title": "位置:",
"checkType": 6,
"required": "Y",
"parentId": 3,
"orderNum": 2,
"formDetailsOptions": [
{
"formDetailsOptionsId": 1,
"formDetailsId": 5,
"orderNum": 1,
"optionDesc": "單位大門",
"defectOpts": "N",
"additionOpts": "N",
"selected": "N"
},
{
"formDetailsOptionsId": 2,
"formDetailsId": 5,
"orderNum": 2,
"optionDesc": "廚房門",
"defectOpts": "N",
"additionOpts": "N",
"selected": "N"
},
{
"formDetailsOptionsId": 3,
"formDetailsId": 5,
"orderNum": 3,
"optionDesc": "廁所客廳",
"defectOpts": "N",
"additionOpts": "N",
"selected": "N"
}
]
},
{
"formDetailsId": 6,
"formId": 1,
"title": "假框抆塞:",
"checkType": 4,
"required": "Y",
"parentId": 3,
"orderNum": 3,
"answerVal": "Y",
"formDetailsOptions": []
},
{
"formDetailsId": 7,
"formId": 1,
"title": "門框尺寸:",
"checkType": 4,
"required": "Y",
"parentId": 3,
"orderNum": 4,
"answerVal": "Y",
"formDetailsOptions": []
},
{
"formDetailsId": 8,
"formId": 1,
"title": "門框木料:",
"checkType": 4,
"required": "Y",
"parentId": 3,
"orderNum": 5,
"answerVal": "Y",
"formDetailsOptions": []
},
{
"formDetailsId": 9,
"formId": 1,
"title": "門框接口:",
"checkType": 4,
"required": "Y",
"parentId": 3,
"orderNum": 6,
"answerVal": "Y",
"formDetailsOptions": []
},
{
"formDetailsId": 10,
"formId": 1,
"title": "門框色澤:",
"checkType": 4,
"required": "Y",
"parentId": 3,
"orderNum": 7,
"answerVal": "Y",
"formDetailsOptions": []
},
{
"formDetailsId": 11,
"formId": 1,
"title": "磨耳及蟻油:",
"checkType": 4,
"required": "Y",
"parentId": 3,
"orderNum": 8,
"answerVal": "Y",
"formDetailsOptions": []
},
{
"formDetailsId": 12,
"formId": 1,
"title": "防火膠條:",
"checkType": 4,
"required": "Y",
"parentId": 3,
"orderNum": 9,
"answerVal": "Y",
"formDetailsOptions": []
},
{
"formDetailsId": 13,
"formId": 1,
"title": "平正及穩固:",
"checkType": 4,
"required": "Y",
"parentId": 3,
"orderNum": 10,
"answerVal": "Y",
"formDetailsOptions": []
},
{
"formDetailsId": 14,
"formId": 1,
"title": "備註:",
"checkType": 7,
"required": "N",
"parentId": 3,
"orderNum": 11,
"answerVal": "Test group remark",
"formDetailsOptions": []
}
]
}
]
},
{
"formDetailsId": 2,
"formId": 1,
"title": "B. 要改善位置及詳情備註:",
"checkType": 1,
"required": "Y",
"parentId": 0,
"orderNum": 2,
"answerVal": "Test B remark",
"formDetailsOptions": []
}
],
"formDefects": [
{
"formDefectsId": 1,
"formId": 1,
"defectRemark": "Test Remark",
"followActionId": 1,
"reporterType": 1,
"formDefectsImgs": [
{
"formDefectsImgId": 1,
"formDefectsId": 1,
"imgType": 1,
"filePath": "data/images/1/DEFECT-20201228150623123-2F3F4H.jpg",
"orderNum": 1
}
]
}
],
"formVendors": [
{
"formVendorId": 2,
"formId": 1,
"vendorId": "3954",
"orderNum": 2,
"isNextVendor": "N",
"formVendorImgs": [
{
"formVendorImgId": 1,
"formVendorId": 2,
"filePath": "data/images/1/QUERY-20201228151423123-2FF2V4.png",
"orderNum": 1
}
],
"vendor": {
"vendorId": "3954",
"vendorDesc": "博西華",
"vendorDescDisp": "BSH"
}
}
],
"formNextVendors": [
{
"formVendorId": 1,
"formId": 1,
"vendorId": "3985",
"orderNum": 1,
"isNextVendor": "Y",
"formVendorImgs": [
{
"formVendorImgId": 2,
"formVendorId": 1,
"filePath": "data/images/1/QUERY-20201228151423123-VD5F5H.png",
"orderNum": 2
}
],
"vendor": {
"vendorId": "3985",
"vendorDesc": "瑞基",
"vendorDescDisp": "Zuki"
}
}
]
}
With this kind of complex json i would suggest using dart packages for serialization. For example:
https://pub.dev/packages/json_serializable
or
https://pub.dev/packages/built_value
If you can share Dart models, then use json_serializable package. That would make things easier. But...
...if you have to live with the JSON response that your colleague developed and you cannot share your models that convert from/to Json, one alternative would be to use https://app.quicktype.io/
I entered your JSON response and out came generated Dart code that seems legit, at a first glance at least.
Example from that code generation:
factory ComplexJson.fromJson(Map<String, dynamic> json) => ComplexJson(
formId: json["formId"],
formTypeId: json["formTypeId"],
formTemplateId: json["formTemplateId"],
version: json["version"],
history: historyValues.map[json["history"]],
refNum: json["refNum"],
dateOfAcceptance: json["dateOfAcceptance"],
dateOfReacceptance: json["dateOfReacceptance"],
blockId: json["blockId"],
floorId: json["floorId"],
flatId: json["flatId"],
isPublic: historyValues.map[json["isPublic"]],
locationId: json["locationId"],
fromFloorId: json["fromFloorId"],
toFloorId: json["toFloorId"],
elevationId: json["elevationId"],
isNextVendor: historyValues.map[json["isNextVendor"]],
isMultipleVendor: historyValues.map[json["isMultipleVendor"]],
formStatusId: json["formStatusId"],
checkResults: json["checkResults"],
submissionDate: json["submissionDate"],
submittedBy: json["submittedBy"],
siteId: json["siteId"],
formDetails: List<MDetail>.from(json["formDetails"].map((x) => MDetail.fromJson(x))),
formDefects: List<FormDefect>.from(json["formDefects"].map((x) => FormDefect.fromJson(x))),
formVendors: List<FormVendor>.from(json["formVendors"].map((x) => FormVendor.fromJson(x))),
formNextVendors: List<FormVendor>.from(json["formNextVendors"].map((x) => FormVendor.fromJson(x))),
);

How to select a particular object from a postgres jsonb column

I am storing the assessments of students in a jsonb column call assessment, every row in the database stores the assessments of students for a particular subject, and i am trying to get a query that will help retrieve:
1. A student assessment for a particular subject.
2. All the student assessments for every subject offer by the student.
Here is a same of the result i get when i select all records from the table.
[
{
"id": "22670f29-1437-4af1-b907-f6940377a851",
"sessionId": 3,
"sectionId": 4,
"subjectId": 8,
"assessment": [
{
"exam": 50,
"grdae": "A",
"total": 79,
"position": "First",
"student_id": 2,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Aristotle"
},
{
"exam": 50,
"grdae": "B",
"total": 69,
"position": "Third",
"student_id": 3,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Elvis"
}
]
},
{
"id": "beca9d97-0d0a-4d89-b8c5-c9a6fed812a5",
"sessionId": 3,
"sectionId": 4,
"subjectId": 10,
"assessment": [
{
"exam": 50,
"grdae": "A",
"total": 79,
"position": "First",
"student_id": 2,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Aristotle"
},
{
"exam": 50,
"grdae": "B",
"total": 69,
"position": "Third",
"student_id": 3,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Elvis"
}
]
},
{
"id": "1ed9c3d6-2482-4b1d-ab59-b77a8933699c",
"sessionId": 3,
"sectionId": 4,
"subjectId": 9,
"assessment": [
{
"exam": 50,
"grdae": "A",
"total": 90,
"position": "First",
"student_id": 2,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Aristotle"
},
{
"exam": 50,
"grdae": "B",
"total": 69,
"position": "Third",
"student_id": 3,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Elvis"
}
]
}
]
This result contains assessment for the different subjects, with subjectIds, 8, 9 ,and 10 for two students with ids 2 and 3.
NOTE: sessionID,SectionID and subjectId are also columns in the table call assessment.
I should be able to get this object in return if i want a student with id 2 assessment for a subjectId of 9 and sessionId is 3 and also sectionId is 4:
{
"exam": 50,
"grdae": "A",
"total": 90,
"position": "First",
"student_id": 2,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Aristotle"
}
And i should be a to get this result, if i want a student with id 2 assessment for all three subjectIds, i.e id 8, 9, 10, and sessionId is 3 and also sectionId is 4:
[
{
"exam": 50,
"grdae": "A",
"total": 90,
"position": "First",
"student_id": 2,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Aristotle"
},
{
"exam": 50,
"grdae": "A",
"total": 79,
"position": "First",
"student_id": 2,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Aristotle"
},
{
"exam": 50,
"grdae": "A",
"total": 79,
"position": "First",
"student_id": 2,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Aristotle"
}
]
Minimized your data in the fiddle to:
[
{
"sessionId": 3,
"sectionId": 4,
"subjectId": 8,
"assessment": [
{
"student_id": 2
},
{
"student_id": 3
}
]
},
{
"sessionId": 3,
"sectionId": 4,
"subjectId": 10,
"assessment": [
{
"student_id": 2
},
{
"student_id": 3
}
]
},
{
"sessionId": 3,
"sectionId": 4,
"subjectId": 9,
"assessment": [
{
"student_id": 2
},
{
"student_id": 3
}
]
}
]
demo:db<>fiddle
The first step is to unnest the relevant id information:
SELECT
assessments,
(elems ->> 'sessionId')::int as session_id,
(elems ->> 'sectionId')::int as section_id,
(elems ->> 'subjectId')::int as subject_id,
(assessments ->> 'student_id')::int AS student_id
FROM
mytable,
json_array_elements(jsondata) as elems,
json_array_elements(elems -> 'assessment') as assessments
This results in:
assessments | session_id | section_id | subject_id | student_id
:--------------- | ---------: | ---------: | ---------: | ---------:
{"student_id":2} | 3 | 4 | 8 | 2
{"student_id":3} | 3 | 4 | 8 | 3
{"student_id":2} | 3 | 4 | 10 | 2
{"student_id":3} | 3 | 4 | 10 | 3
{"student_id":2} | 3 | 4 | 9 | 2
{"student_id":3} | 3 | 4 | 9 | 3
The json_array_elements() function unnest the json array into one record per array element. Because there are two nested arrays, you need to call this function twice. You can get the values of each level as you can see within the SELECT list.
After that you are able to filter whatever you want within the WHERE clause. The resulting records (the relevant assessment objects) can be grouped with json_agg() aggregate function:
SELECT
json_agg(assessments)
FROM (
-- query from above
) s
WHERE session_id IN (3)
AND section_id IN (4)
AND subject_id IN (9) -- only one subject
AND student_id IN (2)
or
SELECT
json_agg(assessments)
FROM (
-- query from above
) s
WHERE session_id IN (3)
AND section_id IN (4)
AND subject_id IN (8,9,10) -- more subjects
AND student_id IN (2)

Sort multiple condition MongoDB

I have collection of user, and this is the following of documents :
{ "_id": 1, "name": "A", "online": 1, "like": 10, "score": 1 },
{ "_id": 2, "name": "B", "online": 0, "like": 9, "score": 0 },
{ "_id": 3, "name": "C", "online": 0, "like": 8, "score": 1 },
{ "_id": 4, "name": "D", "online": 1, "like": 8, "score": 0 },
{ "_id": 5, "name": "E", "online": 1, "like": 7, "score": 1 },
{ "_id": 6, "name": "F", "online": 0, "like": 10, "score": 1 },
{ "_id": 7, "name": "G", "online": 0, "like": 5, "score": 0 },
{ "_id": 8, "name": "H", "online": 0, "like": 13, "score": 0 }
{ "_id": 9, "name": "I", "online": 0, "like": 6, "score": 0 }
I want to show the list of users with some of criterias and ordering with some conditons, online users and most liked in the top of the list,after online user list is show offline users with most scored & most liked. The following of rules :
If online is 1 must be sort by descending of like.
If online is 0 and score is 1 must be sort by descending of score.
If online is 0 and score is 0 must be sort by descending of like.
So, the result can be like :
{ "_id": 1, "name": "A", "online": 1, "like": 10, "score": 1 },
{ "_id": 4, "name": "D", "online": 1, "like": 8, "score": 0 },
{ "_id": 5, "name": "E", "online": 1, "like": 7, "score": 1 },
{ "_id": 6, "name": "F", "online": 0, "like": 10, "score": 1 },
{ "_id": 3, "name": "C", "online": 0, "like": 8, "score": 1 },
{ "_id": 8, "name": "H", "online": 0, "like": 13, "score": 0 }
{ "_id": 2, "name": "B", "online": 0, "like": 9, "score": 0 },
{ "_id": 9, "name": "I", "online": 0, "like": 6, "score": 0 },
{ "_id": 7, "name": "G", "online": 0, "like": 5, "score": 0 }
I have finished until point 2, my query following :
db.users.aggregate([
{
$project :
{
"id" : 1,
"name" : 1,
"online: 1,
"like" : 1,
"score" : 1,
"sort" : {
$cond:
{
"if" :
{
$eq : ["$online", true]
},
"then" : "$like",
"else" : "$score"
}
}
}
},
{
$sort :
{
"online" : -1,
"sort" : -1,
"id" : 1
}
},
{
$skip : 0
},
{
$limit : 9
}
])
But I have the current result following :
{ "_id": 1, "name": "A", "online": 1, "like": 10, "score": 1 },
{ "_id": 4, "name": "D", "online": 1, "like": 8, "score": 0 },
{ "_id": 5, "name": "E", "online": 1, "like": 7, "score": 1 },
{ "_id": 6, "name": "F", "online": 0, "like": 10, "score": 1 },
{ "_id": 3, "name": "C", "online": 0, "like": 8, "score": 1 },
{ "_id": 2, "name": "B", "online": 0, "like": 9, "score": 0 },
{ "_id": 7, "name": "G", "online": 0, "like": 5, "score": 0 },
{ "_id": 8, "name": "H", "online": 0, "like": 13, "score": 0 }
{ "_id": 9, "name": "I", "online": 0, "like": 6, "score": 0 },
You can see, based on point 3, instance { "_id": 8, "name": "H", "online": 0, "like": 13, "score": 0 } should be on top with score is 0
First create additional column call point with value (1 - online)*score
After this sort data by:
online desc
point desc (online = 1 pointbe always 0, online is 0 point is score)
like desc
You can use this query
db.yourtable.aggregate(
[
{ $project:{
"id" : 1,
"name" : 1,
"online": 1,
"like" : 1,
"score" : 1,
point: { $multiply: [
{$subtract: [1,"$online"]}
, "$score"
]}
}
}
,{ $sort : { online: -1, point : -1, like : -1 } }
]
);
Please check below query :
db.getCollection('yourTable').aggregate([
{
$project :
{
"id" : 1,
"name" : 1,
"online": 1,
"like" : 1,
"score" : 1,
onlineSortLike: {
$cond: {
if: { $and: [{ $eq: ['$online',1 ] }] },
then: '$like',
else: 0,
},
},
sortOfflineScore: {
$cond: {
if: { $and: [{ $eq: ['$online',0] }] },
then: '$score',
else: 0,
},
},
sortOfflineScoreLike: {
$cond: {
if: { $and: [{ $eq: ['$online', 0] }] },
then: '$like',
else: 0,
},
},
}
},
{
$sort :
{
"online" : -1,
"onlineSortLike" : -1,
"sortOfflineScore" : -1,
"sortOfflineScoreLike" : -1
}
},
{
$skip : 0
},
{
$limit : 9
}
])