mongodb filter array of nested documents - mongodb-query

I want to find one and filter profile like that by moduleId and name
{
"moduleId": 1,
"access": {
"del": ..,
"editWrite": ...,
"read": ....
}
}
the document looks like this:
"profileAccess": [
{
"moduleId": 1,
"access": {
"del": true,
"editWrite": true,
"read": true
}
},
{
"moduleId": 2,
"access": {
"del": true,
"editWrite": true,
"read": true
}
}
],
"name": "admin"
},

found the answer it seems i forget to return the response
Profile.findOne({name:"admin"},{profileAccess: { $elemMatch: { moduleId: 1} }});

Related

How to group by in MongoDB Compass based on the time?

Recently I'm working with a Mongodb database. Here is the data model of the document I need to run a query on:
{
"creation_date": {
"$date": {
"$numberLong": "1641981205813"
}
},
"user_id": {
"$oid": "61dedd8b7a520461dd78016b"
},
"products": [
{
"_id": {
"$oid": "61dede397a520461dd7818bd"
},
"product_id": {
"$oid": "615071ae8b66e1e9a3d6ea50"
},
"payment": true,
"support_all_payment": false,
"term_ids": null
}
],
"carts_info": [
{
"_id": {
"$oid": "61dede397a520461dd7818be"
},
"support_type": null,
"support_price": 0,
"product_price": 11000,
"product_type": "all",
"final_price": 11000,
"product_id": {
"$oid": "615071ae8b66e1e9a3d6ea50"
}
}
],
"_des": "initial_payment",
"_type": "online",
"_token": "9e0cb4d111f642f1a6f482bb04f1f57b",
"_price": 11000,
"_status": "unpaid",
"_terminal_id": "12605682",
"__v": 0,
"additional_information": {
"saman_bank": {
"MID": "0",
"ResNum": "61dede387a520461dd7818bb",
"State": "CanceledByUser",
"TraceNo": "",
"Wage": "",
"Rrn": "",
"SecurePan": "",
"HashedCardNumber": "",
"Status": "1"
}
}
}
This collection is user orders. I need to count the orders for today. So, I need such a equivalent query for Mongodb Compass the same as this SQL:
SELECT count(1) num,
date(creation_date) date
FROM orders
WHERE date(creation_date) = "2023-02-16"
GROUP BY date
Any idea how can I run this logic on Mongodb Compass?
Use $dateTrunc to perform date only operations.
db.collection.aggregate([
{
"$match": {
$expr: {
$eq: [
{
$dateTrunc: {
date: "$creation_date",
unit: "day"
}
},
ISODate("2022-01-12")
]
}
}
},
{
$group: {
_id: {
$dateTrunc: {
date: "$creation_date",
unit: "day"
}
},
num: {
$sum: 1
}
}
}
])
Mongo Playground
For OP's MongoDB v3.6, we can use $dateToString to perform string comparison on a date-only string.
db.collection.aggregate([
{
$addFields: {
dateOnly: {
"$dateToString": {
"date": "$creation_date",
"format": "%Y-%m-%d"
}
}
}
},
{
$match: {
dateOnly: "2022-01-12"
}
},
{
$group: {
_id: null,
num: {
$sum: 1
}
}
}
])
Mongo Playground

Indexing custom properties with Google Cloud Search API

We are having issues indexing metadata with items added to Google Cloud Search with 3rd-party datasources, using the REST API. We are following this guide: https://developers.google.com/cloud-search/docs/guides/schema-guide.
What we tried: uploaded the schema successfully ✅, indexed some items ✅, made them available in the search UI ✅, but it seems the properties and facets not showing up whether it’s in the green metadata bits in search results or in API results -- we get an empty structuredData object. Search results seem to only query the content.inlineContent and nothing else. We’re not getting any errors from the API when we make the index request (using https://developers.google.com/cloud-search/docs/reference/rest/v1/indexing.datasources.items/index_). It seems like it’s just ignoring everything in structuredData.
Other attempts: In addition to the REST API, we’ve also used the official nodejs SDK, (which has additional validation because it’s in TypeScript), to no avail. We’ve verified that auth params are correct (it returns 401 otherwise) and that there are no other validation issues (it returns 400 otherwise). Requests return 200 and do upload successfully, just not the structuredData. The original schema upload was also successful (200), and the response included the full schema we gave.
What are we missing?
schema JSON:
{
"objectDefinitions": [{
"name": "page",
"options": {
"displayOptions": {
"objectDisplayLabel": "Page",
"metalines": [
{
"properties": [
{
"propertyName": "title"
},
{
"propertyName": "content"
},
{
"propertyName": "author"
},
{
"propertyName": "siteSection"
}
]
}
]
}
},
"propertyDefinitions": [
{
"name": "title",
"isReturnable": true,
"isWildcardSearchable": true,
"isSuggestable": true,
"isRepeatable": false,
"isFacetable": false,
"textPropertyOptions": {
"operatorOptions": {
"operatorName": "title"
}
},
"displayOptions": {
"displayLabel": "Title"
}
},
{
"name": "content",
"isReturnable": true,
"isRepeatable": false,
"isFacetable": false,
"htmlPropertyOptions": {
"retrievalImportance": {
"importance": "DEFAULT"
}
},
"displayOptions": {
"displayLabel": "Content"
}
},
{
"name": "author",
"isReturnable": true,
"isRepeatable": true,
"isFacetable": true,
"textPropertyOptions": {
"operatorOptions": {
"operatorName": "author"
}
},
"displayOptions": {
"displayLabel": "Author(s)"
}
},
{
"name": "siteSection",
"isReturnable": true,
"isWildcardSearchable": false,
"isSuggestable": false,
"isRepeatable": false,
"isFacetable": true,
"textPropertyOptions": {
"operatorOptions": {
"operatorName": "sitesection"
}
},
"displayOptions": {
"displayLabel": "Site Section"
}
}
]
}]
}
indexing code:
const version = '4';
const apiUrl = `https://cloudsearch.googleapis.com/v1/indexing/datasources/${sourceId}/items/exampleItem:index`;
const title = "Example Item";
const url = "https://example.com";
fetch(apiUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + token,
},
body: JSON.stringify({
item: {
name: `datasource/${sourceId}/items/exampleItem`,
acl: {
readers: [
{
gsuitePrincipal: {
gsuiteDomain: true,
},
},
],
},
metadata: {
title: title,
sourceRepositoryUrl: url,
objectType: "page",
},
structuredData: {
object: {
properties: [
{
name: "title",
textValues: {
values: [title],
},
},
{
name: "author",
textValues: {
values: ["Unknown Author"],
},
},
{
name: "siteSection",
textValues: {
values: ["exampleSection"],
},
},
{
name: "content",
htmlValues: {
values: [exampleContentHTML],
},
},
],
},
},
content: {
inlineContent: b64(exampleContentHTML),
contentFormat: "TEXT",
},
version: b64(version),
itemType: "CONTENT_ITEM",
},
mode: "SYNCHRONOUS",
}),
})
indexing result:
{
"name": "datasources/DATASOURCE_ID/items/exampleItem",
"acl": {
"readers": [{
"gsuitePrincipal": {
"gsuiteDomain": true
}
}]
},
"metadata": {
"title": "Example Item",
"sourceRepositoryUrl": "https://example.com",
"objectType": "page"
},
"structuredData": {
"object": {}
},
"content": {
"inlineContent": "... base 64 encoded content...",
"contentFormat": "TEXT"
},
"version": "NQ==",
"status": {
"code": "ACCEPTED"
},
"queue": "default",
"itemType": "CONTENT_ITEM"
}

MongoDB Lookup values based on dynamic field name

I'm pretty sure the below can be done, I'm struggling to understand how to do it in MongoDB.
My data is structured like this (demo data):
db={
"recipes": [
{
"id": 1,
"name": "flatbread pizza",
"ingredients": {
"1010": 1,
"1020": 2,
"1030": 200
}
},
{
"id": 2,
"name": "cheese sandwich",
"ingredients": {
"1040": 1,
"1050": 2
}
}
],
"ingredients": [
{
"id": 1010,
"name": "flatbread",
"unit": "pieces"
},
{
"id": 1020,
"name": "garlic",
"unit": "clove"
},
{
"id": 1030,
"name": "tomato sauce",
"unit": "ml"
},
{
"id": 1040,
"name": "bread",
"unit": "slices"
},
{
"id": 1050,
"name": "cheese",
"unit": "slices"
}
]
}
The output I'm trying to achieve would look like this:
[
{
"id": 1,
"name": "flatbread pizza",
“flatbread”: “1 pieces”,
“garlic”: “2 cloves”,
“tomato sauce”: “200 ml”
},
{
"id": 2,
"name": "cheese sandwich",
“bread”: “1 slices”,
“cheese”: “2 slices”
}
]
I've tried several approaches, and I get stuck at the bit where I need to do a lookup based on the ingredient name (which actually is the id). I tried using $objectToArray to turn it into a k-v document, but then I get stuck in how to construct the lookup pipeline.
This is not a simple solution, and probably can be improved:
db.recipes.aggregate([
{
"$addFields": {
ingredientsParts: {
"$objectToArray": "$ingredients"
}
}
},
{
$unwind: "$ingredientsParts"
},
{
"$group": {
_id: "$id",
name: {
$first: "$name"
},
ingredientsParts: {
$push: {
v: "$ingredientsParts.v",
id: {
$toInt: "$ingredientsParts.k"
}
}
}
}
},
{
"$lookup": {
"from": "ingredients",
"localField": "ingredientsParts.id",
"foreignField": "id",
"as": "ingredients"
}
},
{
$unwind: "$ingredients"
},
{
"$addFields": {
"ingredientsPart": {
"$filter": {
input: "$ingredientsParts",
as: "item",
cond: {
$eq: [
"$$item.id",
"$ingredients.id"
]
}
}
}
}
},
{
$project: {
ingredients: 1,
ingredientsPart: {
"$arrayElemAt": [
"$ingredientsPart",
0
]
},
name: 1
}
},
{
"$addFields": {
units: {
k: "$ingredients.name",
v: {
"$concat": [
{
$toString: "$ingredientsPart.v"
},
" ",
"$ingredients.unit"
]
}
}
}
},
{
$group: {
_id: "$_id",
name: {
$first: "$name"
},
units: {
$push: "$units"
}
}
},
{
"$addFields": {
"data": {
"$arrayToObject": "$units"
}
}
},
{
"$addFields": {
"data.id": "$_id",
"data.name": "$name"
}
},
{
"$replaceRoot": {
"newRoot": "$data"
}
}
])
You can see it works here
As rickhg12hs said, it can be modeled better.

How to use a nested json-based formation value in the jQuery.dataTables?

Now suppose I have a json data formation like this following:
{
"ServiceName": "cacheWebApi",
"Description": "This is a CacheWebApiService",
"IsActive": true,
"Urls": [{ "ServiceAddress": "http://192.168.111.210:8200", "Weight": 5, "IsAvailable": true },
{ "ServiceAddress": ",http://192.168.111.210:8200", "Weight": 3, "IsAvailable": true }]
}
Now what worries me is that the "Urls" is another nested json formation. So how to bind this value to the datatables? And have you got any good ideas (e.g:something like I only wanna show all the ServiceAddress)...
This should do what you need:
var data = [{
"ServiceName": "cacheWebApi",
"Description": "This is a CacheWebApiService",
"IsActive": true,
"Urls": [
{
"ServiceAddress": "http://192.168.111.210:8200",
"Weight": 5,
"IsAvailable": true
},
{
"ServiceAddress": ",http://192.168.111.210:8200",
"Weight": 3,
"IsAvailable": true
}
]
}];
$(function() {
var table = $('#example').dataTable({
"data": data,
"columns": [
{
"data": "ServiceName"
}, {
"data": "Description"
}, {
"data": "IsActive"
}, {
"data": "Urls[0].ServiceAddress"
}, {
"data": "Urls[0].Weight"
}, {
"data": "Urls[0].IsAvailable"
}, {
"data": "Urls[1].ServiceAddress"
}, {
"data": "Urls[1].Weight"
}, {
"data": "Urls[1].IsAvailable"
}
],
});
});
You should put your data in an array though. Working JSFiddle
EDIT
IF the number of Urls isn't defined then you could do something like this:
var table = $('#example').dataTable({
"data": data,
"columns": [
{
"data": "ServiceName"
}, {
"data": "Description"
}, {
"data": "IsActive"
}, {
"data": "Urls",
"render": function(d){
return JSON.stringify(d);
}
}
],
});
I guess that that isn't brilliant but you could do almost anything to that function, for instance:
var table = $('#example').dataTable({
"data": data,
"columns": [
{
"data": "ServiceName"
}, {
"data": "Description"
}, {
"data": "IsActive"
}, {
"data": "Urls",
"render": function(d){
return d.map(function(c){
return c.ServiceAddress
}).join(", ");
}
}
],
});

Cannot get Buttons csv working in DataTables 1.10.11

I am upgrading an existing site that was using DataTables 1.9.4 and TableTools 2.0.3 to use DataTables 1.10.11. I cannot get the csv button to show up on my page.
I replaced
"oTableTools": {
"sSwfPath": "scripts/jquery/TableTools-2.0.3/media/swf/copy_csv_xls.swf",
"sRowSelect": "multi",
"aButtons": [
{
"sExtends": "text",
"sButtonText": t.cmdMarkSelectedInvoiced,
"fnClick": function (nButton, oConfig, oFlash) {
vr.markSelectedInvoiced();
}
},
{
"sExtends": "csv",
"sButtonText": t.cmdExportSelectedToCSV,
"bSelectedOnly": true
},
{
"sExtends": "csv",
"sButtonText": t.cmdExportAllToCSV
},
{
"sExtends": "select_none",
"sButtonText": t.cmdDeselectAll
}
]
},
with
"buttons": ['csv'],
the new initialization for the datatable is:
var bla = $('#someelement').DataTable({
"buttons": [
'csv'
],
"pagingType": "simple",
"destroy": true,
"stateSave": true,
"stateSaveCallback": function (settings, data) {
vr.saveDtState(data);
},
"stateLoadCallback": function (settings) {
return vr.dtSavedState(settings);
},
"pageLength": 10,
"language": {
"emptyTable": t.tblInfoNoDesignRequestFound,
"infoEmpty": t.tblInfoNoDesignRequestFound,
"zeroRecords": t.tblInfoNoDesignRequestFound,
"info": ct.tblInfoTxtDisplayingXtoYofTotal,
"infoFiltered": ct.tblInfoTxtFilteredFromMax,
"lengthMenu": ct.tblInfoTxtShow + ' <select>' + '<option selected value=10>10</option>' + '<option value=15>15</option>' + '<option value=20>20</option>' + '<option value=25>25</option>' + '<option value=-1>' + ct.txtAll + '</option>' + '</select> ' + ct.tblInfoTxtRows,
"search": ct.tblInfoTxtFilter,
"paginate": {
"next": ct.tblInfoTxtNextPage,
"previous": ct.tblInfoTxtPreviousPage
}
},
"ordering": true,
"order": [],
"stripeClasses": [
'myodd',
'myeven'
],
"data": vr.dataObj.data,
"columns": [
{
"data": "companyLocation",
"title": ct.chCompanyLocation
},
{
"data": function (source, type, val) {
if (type === 'display' || type === 'filter') {
return u.jsonToLocalDate(source.requestStatusDateUtc, false);
}
return source.requestStatusDateUtc;
},
"title": ct.chDate
},
{
"data": function (source, type, val) {
return vr.formattedNameSizeAndOrient(source, type)
},
"title": ct.chLogoName
},
{
"data": function (source, type, val) {
return vr.formattedDrInfo(source, type)
},
"title": ct.chDRNumber
},
{
"data": "requestStatusDescription",
"title": ct.chStatus
},
{
"data": "invoiceAmount",
"title": ct.chInvoiceAmount,
"orderable": false,
"className": "rightJustify"
},
{
"data": "invoiceCurrency",
"bSortable": false
},
{
"data": "requestedBy",
"title": ct.chCreatedByName,
"orderable": false
}
],
"initComplete": function () {
vr.loadColumnSelects('viewRequestsDataTable', this, columnSelects);
}
});
You need to specify the dom: parameter.