How to map Elasticsearch match_phrase query in flutter - flutter

I am trying to add elasticsearch to my flutter app.
I am using elastic_client to deal with the connection
How can I map the following query in flutter format?
POST /books/_search
{
"query": {
"match_phrase": {
"name" : {
"query" : "Roberts book",
"slop": 50
}
}
}
}
There is very little info about elasticsearch and flutter.
Right now I have the following code to do the query with elastic_client. But as far as I understand this package did not have the match_phrase implemented. And I need to query match_phrase.
final searchResult = await client.search(
index: 'books',
type: '_doc',
query: elastic.Query.term('name', ['$searchQuery'.toLowerCase()]),
source: true);
I followed this tutorial if you want to know more.
Update
With the help of #Vlad and the creator of the elastic_client
It might be useful for someone, so the full solution is:
final transport = HttpTransport(url: 'http://myip:9200/');
final client = elastic.Client(transport);
final searchResult = await client.search(
index : 'books',
type: '_doc',
query: {
"match_phrase": {
"name" : {
"query" : '$searchQuery'.toLowerCase(),
"slop": 50,
},
},
});

By following the match implementation source code, it looks like that these methods are just wrappers to create JSON. So based on that, I can derive, that you could do the following:
final searchResult = await client.search(
index: 'books',
type: '_doc',
query: {
'match_phrase': {
'name': {
'query': '$searchQuery'.toLowerCase(),
'slop': 50
}
},
};
source: true);
Note, that I have no experience with Flutter, this is just my thinking based on the source code.
Alternatively, you could create your own method which creates JSON for Elasticsearch.

Related

How to query data from `PostgresSql`?

I use NestJj,PostgreSQL and Graphql for Back-End,
Flutter,graphql_flutter for Front End.
I have a collection store like this :
I want to get the following result:
[
{
type:'A',
details:[
{name:'Food1'}
]
},
{
type:'Expense',
details:[
{name:'gym'},
{name:'Dinner'}
]
},
{
type:'Revenue',
details:[
{name:'Revenue'}
]
}
]
For show on the device :
How can I query?
Could you help me?
I'm not sure if you'll be able to build that structure at the level of SQL.
What you can do is to extract the data from the table wit the structure as it is and then map it at the level of JS.
// here's an example with TypeORM
const data = await Collection.findBy({...});
const result = data.map(item => ({
type: item.type,
details: [{
name: item.name
}]
}));
P.S. I'm pretty sure that's not the answer you've expected but it will solve your issue.

Does migrating from MongoDB to SQL breaks basic Strapi queries?

const PostPopulateObj = () => ({
path: 'posts',
model: 'Post',
select: 'id order title alias',
...({ match: { published_at: { $ne: null } } })
})
const GroupPopulateObj = {
path: 'groups',
model: 'Group',
select: 'id order label posts groups'
}
module.exports = {
async getNavigationByAlias(ctx) {
const { alias } = ctx.params
const nav = await strapi.query('navigation').find({ alias }, [
{
...GroupPopulateObj,
populate: [PostPopulateObj, {
...GroupPopulateObj,
populate: PostPopulateObj
}]
},
PostPopulateObj
])
return nav.length > 0 ? nav : null
}
};
I have this and using PostgresSQL instead of MongoDB breaks the above query. But my understanding is that it shouldn't break basic queries and only custom queries as shown in the documentations.
https://docs-v3.strapi.io/developer-docs/latest/development/backend-customization.html#queries
https://github.com/strapi/migration-scripts/tree/main/v3-mongodb-v3-sql
I used the scripts and was able to repopulate the db, but like I said I am getting different results, where I am getting some generic default post (converted null post?) instead of 2 specific posts. The post now returned by Postgres seems to not be inside the db, not sure what's going on, but for some reason it's not returning an error.
A little below the section, they mention custom queries and how to use Bookshelf and Mongoose. I used the Mongoose library for custom queries in my understanding, but the above doesn't use Bookshelf or Mongoose at all, so it should work.

Prisma.io + Full Text Search + PostgreSQL: Search is only working with exact match

I have enabled full text search for prisma and I would like to search the email field returning all entries that match.
I got the following code:
const data = await this.prismaService.merchant.findMany({
where: {
email: {
search: '12rwqg13tr222vqfgedvqrw22#someprovider.de',
},
},
});
This is working when I enter the exact email address. However, when I try to search for a part of it, i.e. 12rwqg13tr222vqfgedvqrw22#someprovider, I get no results.
Do I have to create indexes to accomplish this? In the docs it is mentioned that I only need indexes for PostgreSQL if I want to speed up the queries. Am I missing something here?
apparently I was looking at the wrong feature. contains is what I was looking for:
const res = await prisma.post.findMany({
where: {
author: {
email: {
contains: 'prisma.io',
},
},
},
})
Edit: If you need case insensitive search, have a look at the prisma docs for case sensitivity
const res = await prisma.post.findMany({
where: {
author: {
email: {
contains: 'prisma.io',
mode: 'insensitive',
},
},
},
})
This would match Prisma.IO as well.

how to find multiple data in mongoose?

I cannot see data matching status and name this way. When I run this, the status and name are searching separately. but I want to get the data matching both.
return await Product.find({
$or: [
{ status: args.status },
{ product_name: args.product_name}
]
}).sort({ createdAt: "desc" });
I tried filter and aggregate but I could not get the correct data.
status can be null. $and it doesn't work for me.
solved
let filter = {};
if (args.status) {
filter.status = args.status;
}
if (args.product_name) {
filter.product_name = args.product_name;
}
const result = await Product.find({
...filter
}).sort({ createdAt: "desc" });
return result;
If you want to find products where status == args.status and product_name == args.product_name you would pass a query object like this:
{
status: args.status,
product_name: args.product_name
}
Edit
It sounds like you want to build the filter document depending on available parameters. It might look something like this.
let filter = {}
if (args.status) {
filter.status = args.status
}
if (args.product_name) {
filter.product_name = args.product_name
}
You would then pass this filter object to the find call.

Implementing pagination in vanilla GraphQL

Every tutorial I have found thus far has achieved pagination in GraphQL via Apollo, Relay, or some other magic framework. I was hoping to find answers in similar asked questions here but they don't exist. I understand how to setup the queries but I'm unclear as to how I would implement the resolvers.
Could someone point me in the right direction? I am using mongoose/MongoDB and ES5, if that helps.
EDIT: It's worth noting that the official site for learning GraphQL doesn't have an entry on pagination if you choose to use graphql.js.
EDIT 2: I love that there are some people who vote to close questions before doing their research whereas others use their knowledge to help others. You can't stop progress, no matter how hard you try. (:
Pagination in vanilla GraphQL
// Pagination argument type to represent offset and limit arguments
const PaginationArgType = new GraphQLInputObjectType({
name: 'PaginationArg',
fields: {
offset: {
type: GraphQLInt,
description: "Skip n rows."
},
first: {
type: GraphQLInt,
description: "First n rows after the offset."
},
}
})
// Function to generate paginated list type for a GraphQLObjectType (for representing paginated response)
// Accepts a GraphQLObjectType as an argument and gives a paginated list type to represent paginated response.
const PaginatedListType = (ItemType) => new GraphQLObjectType({
name: 'Paginated' + ItemType, // So that a new type name is generated for each item type, when we want paginated types for different types (eg. for Person, Book, etc.). Otherwise, GraphQL would complain saying that duplicate type is created when there are multiple paginated types.
fields: {
count: { type: GraphQLInt },
items: { type: new GraphQLList(ItemType) }
}
})
// Type for representing a single item. eg. Person
const PersonType = new GraphQLObjectType({
name: 'Person',
fields: {
id: { type: new GraphQLNonNull(GraphQLID) },
name: { type: GraphQLString },
}
})
// Query type which accepts pagination arguments with resolve function
const PersonQueryTypes = {
people: {
type: PaginatedListType(PersonType),
args: {
pagination: {
type: PaginationArgType,
defaultValue: { offset: 0, first: 10 }
},
},
resolve: (_, args) => {
const { offset, first } = args.pagination
// Call MongoDB/Mongoose functions to fetch data and count from database here.
return {
items: People.find().skip(offset).limit(first).exec()
count: People.count()
}
},
}
}
// Root query type
const QueryType = new GraphQLObjectType({
name: 'QueryType',
fields: {
...PersonQueryTypes,
},
});
// GraphQL Schema
const Schema = new GraphQLSchema({
query: QueryType
});
and when querying:
{
people(pagination: {offset: 0, first: 10}) {
items {
id
name
}
count
}
}
Have created a launchpad here.
There's a number of ways you could implement pagination, but here's two simple example resolvers that use Mongoose to get you started:
Simple pagination using limit and skip:
(obj, { pageSize = 10, page = 0 }) => {
return Foo.find()
.skip(page*pageSize)
.limit(pageSize)
.exec()
}
Using _id as a cursor:
(obj, { pageSize = 10, cursor }) => {
const params = cursor ? {'_id': {'$gt': cursor}} : undefined
return Foo.find(params).limit(pageSize).exec()
}