Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Graphql queries to support total when using Lucene queries #11159

Closed
wants to merge 9 commits into from
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
using OrchardCore.Apis.GraphQL.Resolvers;
using OrchardCore.ContentManagement.GraphQL.Queries;
using OrchardCore.Lucene;
using OrchardCore.Lucene.Model;

hyzx86 marked this conversation as resolved.
Show resolved Hide resolved

namespace OrchardCore.Queries.Lucene.GraphQL.Queries
{
Expand Down Expand Up @@ -57,19 +59,32 @@ public async Task BuildAsync(ISchema schema)
FieldType fieldType;

var fieldTypeName = querySchema["fieldTypeName"]?.ToString() ?? query.Name;

if (query.ReturnContentItems &&
type.StartsWith("ContentItem/", StringComparison.OrdinalIgnoreCase))
if (querySchema.ContainsKey("hasTotal") && querySchema["hasTotal"].ToString().Equals("true", StringComparison.OrdinalIgnoreCase))
hyzx86 marked this conversation as resolved.
Show resolved Hide resolved
{
var contentType = type.Remove(0, 12);
fieldType = BuildContentTypeFieldType(schema, contentType, query, fieldTypeName);
if (query.ReturnContentItems && type.StartsWith("ContentItem/", StringComparison.OrdinalIgnoreCase))
{
var contentType = type.Remove(0, 12);
fieldType = BuildTotalContentTypeFieldType(schema, contentType, query, fieldTypeName);
}
else
{
fieldType = BuildTotalSchemaBasedFieldType(query, querySchema, fieldTypeName);
}
}
else
{
fieldType = BuildSchemaBasedFieldType(query, querySchema, fieldTypeName);
if (query.ReturnContentItems && type.StartsWith("ContentItem/", StringComparison.OrdinalIgnoreCase))
{
var contentType = type.Remove(0, 12);
fieldType = BuildContentTypeFieldType(schema, contentType, query, fieldTypeName);
}
else
{
fieldType = BuildSchemaBasedFieldType(query, querySchema, fieldTypeName);
}
}

if (fieldType != null)
if (fieldType != null && !schema.Query.HasField(fieldType.Name))
{
schema.Query.AddField(fieldType);
}
Expand Down Expand Up @@ -149,7 +164,7 @@ private FieldType BuildSchemaBasedFieldType(LuceneQuery query, JToken querySchem
JsonConvert.DeserializeObject<Dictionary<string, object>>(parameters)
: new Dictionary<string, object>();

var result = await queryManager.ExecuteQueryAsync(iquery, queryParameters);
var result = (await queryManager.ExecuteQueryAsync(iquery, queryParameters)) as OrchardCore.Lucene.LuceneQueryResults;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can do the LuceneQueryResults casting in the return

return result.Items;
}),
Type = typeof(ListGraphType<ObjectGraphType<JObject>>)
Expand All @@ -169,8 +184,7 @@ private FieldType BuildContentTypeFieldType(ISchema schema, string contentType,
var fieldType = new FieldType
{
Arguments = new QueryArguments(
new QueryArgument<StringGraphType> { Name = "parameters" }
),
new QueryArgument<StringGraphType> { Name = "parameters" }),

Name = fieldTypeName,
Description = "Represents the " + query.Source + " Query : " + query.Name,
Expand All @@ -185,14 +199,163 @@ private FieldType BuildContentTypeFieldType(ISchema schema, string contentType,
var queryParameters = parameters != null ?
JsonConvert.DeserializeObject<Dictionary<string, object>>(parameters)
: new Dictionary<string, object>();

var result = await queryManager.ExecuteQueryAsync(iquery, queryParameters);
var result = (await queryManager.ExecuteQueryAsync(iquery, queryParameters)) as OrchardCore.Lucene.LuceneQueryResults;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

return result.Items;
}),
Type = typetype.Type
};

return fieldType;
}
private FieldType BuildTotalSchemaBasedFieldType(LuceneQuery query, JToken querySchema, string fieldTypeName)
hyzx86 marked this conversation as resolved.
Show resolved Hide resolved
{
var properties = querySchema["properties"];
if (properties == null)
{
return null;
}
var totalType = new ObjectGraphType<OrchardCore.Lucene.LuceneQueryResults>()
{
Name = fieldTypeName
};

var typetype = new ObjectGraphType<JObject>
{
Name = fieldTypeName
};
var listType = new ListGraphType(typetype);

totalType.Field(listType.GetType(), "items",
resolve: context =>
{
return context.Source?.Items;
});
var total = totalType.Field<IntGraphType>("total",
resolve: context =>
{
return context.Source?.Count;
});


foreach (JProperty child in properties.Children())
{
var name = child.Name;
var nameLower = name.Replace('.', '_');
var type = child.Value["type"].ToString();
var description = child.Value["description"]?.ToString();

if (type == "string")
{
var field = typetype.Field(
typeof(StringGraphType),
nameLower,
description: description,
resolve: context =>
{
var source = context.Source;
return source[context.FieldDefinition.Metadata["Name"].ToString()].ToObject<string>();
});
field.Metadata.Add("Name", name);
}
else if (type == "integer")
{
var field = typetype.Field(
typeof(IntGraphType),
nameLower,
description: description,
resolve: context =>
{
var source = context.Source;
return source[context.FieldDefinition.Metadata["Name"].ToString()].ToObject<int>();
});
field.Metadata.Add("Name", name);
}
}

var fieldType = new FieldType
{
Arguments = new QueryArguments(
new QueryArgument<StringGraphType> { Name = "parameters" }
),

Name = fieldTypeName,
Description = "Represents the " + query.Source + " Query : " + query.Name,
ResolvedType = totalType,
Resolver = new LockedAsyncFieldResolver<object, object>(async context =>
{
var queryManager = context.ResolveServiceProvider().GetService<IQueryManager>();
var iquery = await queryManager.GetQueryAsync(query.Name);

var parameters = context.GetArgument<string>("parameters");

var queryParameters = parameters != null ?
JsonConvert.DeserializeObject<Dictionary<string, object>>(parameters)
: new Dictionary<string, object>();

var result = (await queryManager.ExecuteQueryAsync(iquery, queryParameters)) as OrchardCore.Lucene.LuceneQueryResults;
return result;
}),
Type = totalType.GetType()
};

return fieldType;
}


private FieldType BuildTotalContentTypeFieldType(ISchema schema, string contentType, LuceneQuery query, string fieldTypeName)
{
var typetype = schema.Query.Fields.OfType<ContentItemsFieldType>().FirstOrDefault(x => x.Name == contentType);
if (typetype == null)
{
return null;
}

var totalType = new ObjectGraphType<OrchardCore.Lucene.LuceneQueryResults>
{
Name = fieldTypeName
};

var items = totalType.Field(typetype.Type, "items",
resolve: context =>
{
return context.Source?.Items ?? Array.Empty<object>();
});
items.ResolvedType = typetype.ResolvedType;
totalType.Field<IntGraphType>("total",
resolve: context =>
{
return context.Source?.Count ?? 0;
});

var fieldType = new FieldType
{
Arguments = new QueryArguments(
new QueryArgument<StringGraphType> { Name = "parameters" }),

Name = fieldTypeName,
Description = "Represents the " + query.Source + " Query : " + query.Name,
ResolvedType = totalType,
Resolver = new LockedAsyncFieldResolver<object, object>(async context =>
{
var queryManager = context.ResolveServiceProvider().GetService<IQueryManager>();
var iquery = await queryManager.GetQueryAsync(query.Name);

var parameters = context.GetArgument<string>("parameters");

var queryParameters = parameters != null ?
JsonConvert.DeserializeObject<Dictionary<string, object>>(parameters)
: new Dictionary<string, object>();
var result = await queryManager.ExecuteQueryAsync(iquery, queryParameters);

return result as OrchardCore.Lucene.LuceneQueryResults;
}),
Type = totalType.GetType()
};

return fieldType;
}


}

}