MEAN.JS: Filter in mongoose middleware - express

This is my code in backend controller in MEAN JS:
exports.list = function(req, res) {
// configure the filter using req params
var filters = {
filters : {
optional : {
contains : req.query.filter
}
}
};
var sort = {
asc : {
desc: 'name'
}
};
Province
.find()
.filter(filters)
.order(sort)
.exec(function (err, provinces) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(provinces);
}
});
};
The request:
http://localhost:3000/provinces?filter[name]=provincia de Barcelona
Returns a filtered result, as expected:
[
{
"_id": "54ba72903f51d73c4aff6da6",
"community": "54ba689f5fdfbdea292b8737",
"location": "{lat: '41.386290', lng: '2.184988', zoom: '11'}",
"__v": 0,
"name": "provincia de Barcelona"
}
]
When I use a different attribute, the filter stops working. Example:
http://localhost:3000/provinces?filters[community]=54ba69755fdfbdea292b8738
Return this:
{
"message": ""
}
And console.log(err) return this:
[CastError: Cast to ObjectId failed for value "/54ba689f5fdfbdea292b8737/i" at path "community"]
message: 'Cast to ObjectId failed for value "/54ba689f5fdfbdea292b8737/i" at path "community"',
name: 'CastError',
type: 'ObjectId',
value: /54ba689f5fdfbdea292b8737/i,
path: 'community' }
The original document:
[
{
"_id": "54ba72903f51d73c4aff6da6",
"community": "54ba689f5fdfbdea292b8737",
"location": "{lat: '41.386290', lng: '2.184988', zoom: '11'}",
"__v": 0,
"name": "provincia de Barcelona"
},
{
"_id": "54ba73c33f51d73c4aff6da7",
"community": "54ba69755fdfbdea292b8738",
"location": "{lat: '42.4298846', lng: '-8.644620199999963', zoom: '11'}",
"__v": 0,
"name": "provincia de Pontevedra"
}
]

Maybe is not the best way, but works :)
exports.list = function(req, res) {
var community = {community: ''};
community.community = mongoose.Types.ObjectId(req.query.filter.community);
console.log(community);
var filters = {
filters : {
optional : {
contains : community
}
}
};
var sort = {
asc : {
desc: 'name'
}
};
Province
.find()
.filter(filters)
.order(sort)
.exec(function (err, provinces) {
console.log(err);
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(provinces);
}
});
};
The request:
http://localhost:3000/provinces?filter[community]=54ba689f5fdfbdea292b8737
The result:
[
{
"_id": "54ba72903f51d73c4aff6da6",
"community": "54ba689f5fdfbdea292b8737",
"location": "{lat: '41.386290', lng: '2.184988', zoom: '11'}",
"__v": 0,
"name": "provincia de Barcelona"
}
]

Related

GraphQL pagination partial response with error array

I have a query like below
query {
heroes {
node {
name
}
endCursor
}
}
I am trying to understand how GraphQL can handle the error handling and return partial response. I looked at https://github.com/graphql/dataloader/issues/169 and tried to create a resolver like below;
{
Query: {
heroes: async (_) => {
const heroesData = await loadHeroesFromDataWarehouse();
return {
endCursor: heroesData.endCursor;
node: heroesData.map(h => h.name === 'hulk' ? new ApolloError('Hulk is too powerful') : h)
}
}
}
}
I was hoping it would resolve something like below;
{
"errors": [
{
"message": "Hulk is too powerful",
"path": [
"heroes", "1"
],
}
],
"data": {
"heroes": [
{
"name": "spiderman"
},
null,
{
"name": "ironman"
}
]
}
}
but it is completely failing making the heroes itself null like below;
{
"errors": [
{
"message": "Hulk is too powerful",
"path": [
"heroes"
],
}
],
"data": {
"heroes": null
}
}
How can I make resolver to return me the desired partial response?
Found the solution, basically we need a resolver to resolve the edge model itself;
{
Query: {
heroes: (_) => loadHeroesFromDataWarehouse()
},
HeroesEdge {
node: async (hero) => hero.name === 'hulk' ? new ApolloError('Hulk is too powerful') : hero
}
}

Convert File in MS Graph API on SPFx return undefined

When i try to download a file from API Graph accesing to Drive or Sites with javascript on SPFx this return undefined.
my webpart code:
import { Version } from '#microsoft/sp-core-library';
import {
BaseClientSideWebPart,
IPropertyPaneConfiguration,
PropertyPaneTextField
} from '#microsoft/sp-webpart-base';
import * as strings from 'Docx2PdfWebPartStrings';
import { MSGraphClient } from '#microsoft/sp-http';
export interface IDocx2PdfWebPartProps {
description: string;
}
export default class Docx2PdfWebPart extends BaseClientSideWebPart<IDocx2PdfWebPartProps> {
public async render(): Promise<void> {
const client: MSGraphClient = await this.context.msGraphClientFactory.getClient();
var tenant = 'test';
var siteID = `${tenant}.sharepoint.com,12adb250-26f4-4dbb-9545-71d029bad763,8fdc3f56-2d6d-42d9-9a4d-d684e73c341e`;
var fileID = '01MBNFB7EIQLARTATNE5G3XDJNYBD2A3IL';
var fileName = 'Test.docx';
//This work
var site = await client.api(`/sites/${tenant}.sharepoint.com:/sites/dev:/drive?$select=id,weburl`).get();
console.log(site);
try {
//This not work
var fileFromDrive = await client.api(`/drive/root:/${fileName}:/content?format=pdf`).get();
console.log(fileFromDrive);
var fileFromSite = await client.api(`/sites/${siteID}/drive/items/${fileID}/content?format=pdf`).get();
console.log(fileFromSite);
} catch (error) {
console.log(error);
}
this.domElement.innerHTML = `<h1>Hola Mundo</h1>`;
}
protected get dataVersion(): Version {
return Version.parse('1.0');
}
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
pages: [
{
header: {
description: strings.PropertyPaneDescription
},
groups: [
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneTextField('description', {
label: strings.DescriptionFieldLabel
})
]
}
]
}
]
};
}
}
The chrome console log
But when i use Graph Explorer it works correctly
This is my package-solution.json
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
"solution": {
"name": "docx-2-pdf-client-side-solution",
"id": "f4b5db4f-d9ff-463e-b62e-0cc9c9e94089",
"version": "1.0.0.0",
"includeClientSideAssets": true,
"skipFeatureDeployment": true,
"isDomainIsolated": false,
"webApiPermissionRequests": [
{
"resource": "Microsoft Graph",
"scope": "Sites.Read.All"
},
{
"resource": "Microsoft Graph",
"scope": "Files.Read.All"
},
{
"resource": "Microsoft Graph",
"scope": "Files.ReadWrite.All"
},
{
"resource": "Microsoft Graph",
"scope": "Sites.ReadWrite.All"
}
]
},
"paths": {
"zippedPackage": "solution/docx-2-pdf.sppkg"
}
}
I use the following articles
https://learn.microsoft.com/en-us/graph/api/driveitem-get-content?view=graph-rest-1.0&tabs=javascript
https://learn.microsoft.com/en-us/graph/api/driveitem-get-content-format?view=graph-rest-1.0&tabs=javascript#code-try-1
Try using the callback property instead of await:
client.api(`/drive/root:/${fileName}:/content?format=pdf`).get((err, response) => console.log("your response:", err, response));

Fuzzy search using mongoose from vue client

Getting error unknown top level operator $regex
search.vue `
let questDocuments = await conversation
.find({ query: { $limit: 100, $search: q, skippop: true } })
.then(response => {`
q is the string being passed
service hook
before: {
all: [],
find: [
hookBeforeFind,
search({
fields: ["label"],
deep: true
})
],
Model
const conversation = new Schema(
{
label: { type: String, required: true },
nodeId: { type: String, required: true },
details: { type: String },
url: { type: String },
creator: { type: String },
handle: { type: String },
date: { type: String },
From search bar add expression to search. E.g "the"
Add $regex to the whitelist option of the Mongoose service:
app.use('/messages', service({
Model,
whitelist: [ '$regex' ]
}));
try this
// regex to find records that start with letter any name , example "e"
Model.aggregate([
{
$match: {
field_name: {
$regex: "^" + searchName,
$options: "i"
}
}
}]).exec(function(err, result) {
if (err) { // handle here }
if (result) { // do something }
}

Can't get Data via Graphql from Couchdb Server

I am using Couchdb server running in a Docker Build on my Mac.
To access the Data I run an express app via node.
After Building my Schema for the Graphql and test it with the Graphql Interface, I am able to get the Data from a specific User but not the Document for all the Users from my users resolver.
Here is my Code:
//resolvers
var resolvers = {
users: () => {
var statement = "SELECT META(user).id, user.* FROM `" + bucket._name + "` AS user WHERE user.type = 'user'";
var query = Couchbase.N1qlQuery.fromString(statement);
return new Promise((resolve, reject) => {
bucket.query(query, (error, result) => {
if(error) {
return reject(error);
}
resolve(result);
});
});
},
user: (data) => {
var id = data.id;
return new Promise((resolve, reject) => {
bucket.get(id, (error, result) => {
if (error) {
return reject(error);
}
resolve(result.value);
});
});
}
};
//express setup
app.use("/graphql", ExpressGraphQL({
schema: schema,
rootValue: resolvers,
graphiql: true
}));
app.listen(3000, () => {
console.log("lisntening...")
});
//Schema
var schema = BuildSchema(`
type Query{
user(id: String!): User,
users: [User]
}
type User{
id: String,
profileImage: String,
birthdate: String,
reviews: [String],
premium: Boolean
}
`);
When I try my query like this:
{
users{
id
}
}
i get the following error msg returned:
{
"errors": [
{
"message": "syntax error - at user",
"locations": [
{
"line": 31,
"column": 3
}
],
"path": [
"users"
]
}
],
"data": {
"users": null
}
}
The specific user query from the second resolver works fine!
Here my test document in the Database:
{
"id": "ohuibjnklmönaio",
"profileImage": "pic",
"birthdate": "date",
"reviews": [
"a",
"b"
],
"premium": true,
"type": "user"
}

Elastic Search when to add dynamic mappings

I've been having troubles with Elastic Search (ES) dynamic mappings. Seems like I'm in a catch-22. https://www.elastic.co/guide/en/elasticsearch/guide/current/custom-dynamic-mapping.html
The main goal is to store everything as a string that comes into ES.
What I've tried:
In ES you can't create a dynamic mapping until the index has been
created. Okay, makes sense.
I can't create an empty index, so if
the first item sent into the index is not a string, I can't
re-assign it... I won't know what type of object with be the first
item in the index, it could be any type, due to how the the app accepts a variety of objects/events.
So if I can't create the mapping ahead of time, and I can't insert an empty index to create the mapping, and I can't change the mapping after the fact, how do I deal with the first item if its NOT a string???
Here's what I'm currently doing (using the Javascript Client).
createESIndex = function (esClient){
esClient.index({
index: 'timeline-2015-11-21',
type: 'event',
body: event
},function (error, response) {
if (error) {
logger.log(logger.SEVERITY.ERROR, 'acceptEvent elasticsearch create failed with: '+ error + " req:" + JSON.stringify(event));
console.log(logger.SEVERITY.ERROR, 'acceptEvent elasticsearch create failed with: '+ error + " req:" + JSON.stringify(event));
res.status(500).send('Error saving document');
} else {
res.status(200).send('Accepted');
}
});
}
esClientLookup.getClient( function(esClient) {
esClient.indices.putTemplate({
name: "timeline-mapping-template",
body:{
"template": "timeline-*",
"mappings": {
"event": {
"dynamic_templates": [
{ "timestamp-only": {
"match": "#timestamp",
"match_mapping_type": "date",
"mapping": {
"type": "date",
}
}},
{ "all-others": {
"match": "*",
"match_mapping_type": "string",
"mapping": {
"type": "string",
}
}
}
]
}
}
}
}).then(function(res){
console.log("put template response: " + JSON.stringify(res));
createESIndex(esClient);
}, function(error){
console.log(error);
res.status(500).send('Error saving document');
});
});
Index templates to the rescue !! That's exactly what you need, the idea is to create a template of your index and as soon as you wish to store a document in that index, ES will create it for you with the mapping you gave (even dynamic ones)
curl -XPUT localhost:9200/_template/my_template -d '{
"template": "index_name_*",
"settings": {
"number_of_shards": 1
},
"mappings": {
"type_name": {
"dynamic_templates": [
{
"strings": {
"match": "*",
"match_mapping_type": "*",
"mapping": {
"type": "string"
}
}
}
],
"properties": {}
}
}
}'
Then when you index anything in an index whose name matches index_name_*, the index will be created with the dynamic mapping above.
For instance:
curl -XPUT localhost:9200/index_name_1/type_name/1 -d '{
"one": 1,
"two": "two",
"three": true
}'
That will create a new index called index_name_1 with a mapping type for type_name where all properties are string. You can verify that with
curl -XGET localhost:9200/index_name_1/_mapping/type_name
Response:
{
"index_name_1" : {
"mappings" : {
"type_name" : {
"dynamic_templates" : [ {
"strings" : {
"mapping" : {
"type" : "string"
},
"match" : "*",
"match_mapping_type" : "*"
}
} ],
"properties" : {
"one" : {
"type" : "string"
},
"three" : {
"type" : "string"
},
"two" : {
"type" : "string"
}
}
}
}
}
}
Note that if you're willing to do this via the Javascript API, you can use the indices.putTemplate call.
export const user = {
email: {
type: 'text',
},
};
export const activity = {
date: {
type: 'text',
},
};
export const common = {
name: {
type: 'text',
},
};
import { Client } from '#elastic/elasticsearch';
import { user } from './user';
import { activity } from './activity';
import { common } from './common';
export class UserDataFactory {
private schema = {
...user,
...activity,
...common,
relation_type: {
type: 'join',
eager_global_ordinals: true,
relations: {
parent: ['activity'],
},
},
};
constructor(private client: Client) {
Object.setPrototypeOf(this, UserDataFactory.prototype);
}
async create() {
const settings = {
settings: {
analysis: {
normalizer: {
useLowercase: {
filter: ['lowercase'],
},
},
},
},
mappings: {
properties: this.schema,
},
};
const { body } = await this.client.indices.exists({
index: ElasticIndex.UserDataFactory,
});
await Promise.all([
await (async (client) => {
await new Promise(async function (resolve, reject) {
if (!body) {
await client.indices.create({
index: ElasticIndex.UserDataFactory,
});
}
resolve({ body });
});
})(this.client),
]);
await this.client.indices.close({ index: ElasticIndex.UserDataFactory });
await this.client.indices.putSettings({
index: ElasticIndex.UserDataFactory,
body: settings,
});
await this.client.indices.open({
index: ElasticIndex.UserDataFactory,
});
await this.client.indices.putMapping({
index: ElasticIndex.UserDataFactory,
body: {
dynamic: 'strict',
properties: {
...this.schema,
},
},
});
}
}
wrapper.ts
class ElasticWrapper {
private _client: Client = new Client({
node: process.env.elasticsearch_node,
auth: {
username: 'elastic',
password: process.env.elasticsearch_password || 'changeme',
},
ssl: {
ca: process.env.elasticsearch_certificate,
rejectUnauthorized: false,
},
});
get client() {
return this._client;
}
}
export const elasticWrapper = new ElasticWrapper();
index.ts
new UserDataFactory(elasticWrapper.client).create();