OrchardCore的liquid常用的命令
* if, endif, elsif, else, unless, endunless,
* case, endcase,
* when,
* for, endfor,
* continue, break,
* comment, endcomment,
* raw, endraw,
* cycle, assign,
* capture, endcapture,
* increment, decrement,
* include, render_body,
* render_section, page_title,
* antiforgerytoken,
* layout, shape_clear_alternates,
* shape_add_alternates, shape_clear_wrappers,
* shape_add_wrappers, shape_clear_classes,
* shape_add_classes, shape_clear_attributes,
* shape_add_attributes, shape_type, shape_display_type,
* shape_position, shape_cache, shape_tab,
* shape_remove_item, shape_pager, helper,
* shape, link, meta, resources, script,
* style, block, endblock, a, enda,
* zone, endzone, scriptblock,
* endscriptblock, cache, endcache,
* cache_dependency, cache_expires_on,
* cache_expires_after, cache_expires_sliding
workflow工作流例子
oc 如何在liquid模板中构建数组对象
用于图像列表
{
"value": [
for client in content.Clients.value
{
"ACCOUNTNUM": "",
"EMAIL": "",
"NAME": "",
"PHONE": "",
"VATNUM": "",
"RECID": "",
"CANALID": "",
"CANALDESC": ""
},
endfor
]
}
OrchardCore 删除冗余数据
数据无价,谨慎操作,提前备份,一定要注意匹配的范围
SET @x = '%高晓松%';
DELETE
FROM
ContentItemIndex
WHERE
DocumentId IN (
SELECT
Id
FROM
`Document`
WHERE
Content LIKE @x
);
DELETE
FROM
WorkflowIndex
WHERE
DocumentId IN (
SELECT
Id
FROM
`Document`
WHERE
Content LIKE @x
);
DELETE
FROM
`Document`
WHERE
Content LIKE @x
修改已经生成的文章的url
之前规划的url不想用了,想用一个新的,就需要更新url,直接更新AutoroutePartIndex表。
-- sqlite 数据库
UPDATE AutoroutePartIndex
SET Path = '/spikepost/' || DocumentId
WHERE Path LIKE '%/blogpost/%' ;
WPF 集成 OrchardCore 测试
截图
结果
生成单个exe成功,运行速度有点慢,再次打包遇到Http 500 问题,用vs 20222调试代码的生成速度太慢了,生成的单个文件大小为155MB,我决定放弃这个方向了。
缺点总结
- 生成代码慢非常降低调试速度
- 生成的包太大了,electron才不到100MB
- 代码没有加密过,但是运行速度就是有点慢,可能是webview2造成的,不清楚原因,wpf的webbrowser更难用,直接js报错,使用wpf集成浏览器这个方向还是太新了
模块用例
Set Property 例子
"2 + 2"
"workflowContext.Properties['someProperty']"
"workflowContext.Input['age'] >= 18 ? 'Adult' : 'Minor'"
"workflowContext.Input['name'].toUpperCase()"
"new Date(workflowContext.Input['date']).getFullYear()"
"workflowContext.Input['items'].filter(item => item.price > 100).length"
"JSON.parse(workflowContext.Input['jsonString']).propertyName"
"(() => {
let total = 0;
workflowContext.Input['orders'].forEach(order => total += order.amount);
return total > 1000 ? 'High Value' : 'Standard';
})()"
lucene 查询去重 duplicateFilter
新加入duplicateFilter过滤标签,输入相应的字段就可以去重
{
"query": {
"term" : { "Content.ContentItem.ContentType" : "BlogPost" }
},
"sort": { "Content.ContentItem.CreatedUtc": { "order": "asc" } },
"duplicateFilter": "Title"
}
{
"from" : { { from } } , "size":{ { size } },
"query": {
"term" : { "Content.ContentItem.ContentType" : "{ { inputContentTypeName } }" }
},
"sort": { "Content.ContentItem.CreatedUtc": { "order": "asc" } },
"duplicateFilter": "{ { fliterFieldName } }"
}
//下面的是Query名称的例子
//QueryContentByContentTypeFieldCount
//QueryContentByContentTypeFieldPagenation
去重的代码设置
替换LuceneQueryService文件为下面的文件即可
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.TokenAttributes;
using Lucene.Net.Sandbox.Queries;
using Lucene.Net.Search;
using Newtonsoft.Json.Linq;
namespace OrchardCore.Lucene
{
public class LuceneQueryService : ILuceneQueryService
{
private readonly IEnumerable<ILuceneQueryProvider> _queryProviders;
public LuceneQueryService(IEnumerable<ILuceneQueryProvider> queryProviders)
{
_queryProviders = queryProviders;
}
public Task<LuceneTopDocs> SearchAsync(LuceneQueryContext context, JObject queryObj)
{
var queryProp = queryObj["query"] as JObject;
if (queryProp == null)
{
throw new ArgumentException("Query DSL requires a [query] property");
}
var query = CreateQueryFragment(context, queryProp);
var sortProperty = queryObj["sort"];
var fromProperty = queryObj["from"];
var sizeProperty = queryObj["size"];
string duplicateFilterProperty = queryObj["duplicateFilter"]?.Value<string>() ?? "";
var size = sizeProperty?.Value<int>() ?? 50;
var from = fromProperty?.Value<int>() ?? 0;
string sortField = null;
string sortOrder = null;
string sortType = null;
var sortFields = new List<SortField>();
if (sortProperty != null)
{
if (sortProperty.Type == JTokenType.String)
{
sortField = sortProperty.ToString();
sortFields.Add(new SortField(sortField, SortFieldType.STRING, sortOrder == "desc"));
}
else if (sortProperty.Type == JTokenType.Object)
{
sortField = ((JProperty)sortProperty.First).Name;
sortOrder = ((JProperty)sortProperty.First).Value["order"].ToString();
sortType = ((JProperty)sortProperty.First).Value["type"]?.ToString();
var sortFieldType = SortFieldType.STRING;
if (sortType != null)
{
sortFieldType = (SortFieldType)Enum.Parse(typeof(SortFieldType), sortType.ToUpper());
}
sortFields.Add(new SortField(sortField, sortFieldType, sortOrder == "desc"));
}
else if (sortProperty.Type == JTokenType.Array)
{
foreach (var item in sortProperty.Children())
{
sortField = ((JProperty)item.First).Name;
sortOrder = ((JProperty)item.First).Value["order"].ToString();
sortType = ((JProperty)item.First).Value["type"]?.ToString();
var sortFieldType = SortFieldType.STRING;
if (sortType != null)
{
sortFieldType = (SortFieldType)Enum.Parse(typeof(SortFieldType), sortType.ToUpper());
}
sortFields.Add(new SortField(sortField, sortFieldType, sortOrder == "desc"));
}
}
}
TopDocs docs = null;
if (string.IsNullOrEmpty(duplicateFilterProperty))
{
docs = context.IndexSearcher.Search(query, size + from, (sortField == null) ? Sort.RELEVANCE : new Sort(new SortField(sortField, SortFieldType.STRING, sortOrder == "desc")));
}
else
{
DuplicateFilter filter = new DuplicateFilter(duplicateFilterProperty);
filter.KeepMode = KeepMode.KM_USE_FIRST_OCCURRENCE;
docs = context.IndexSearcher.Search(query, filter, size + from, (sortField == null) ? Sort.RELEVANCE : new Sort(new SortField(sortField, SortFieldType.STRING, sortOrder == "desc")));
}
if (from > 0)
{
docs = new TopDocs(docs.TotalHits - from, docs.ScoreDocs.Skip(from).ToArray(), docs.MaxScore);
}
var collector = new TotalHitCountCollector();
context.IndexSearcher.Search(query, collector);
var result = new LuceneTopDocs { TopDocs = docs, Count = collector.TotalHits };
return Task.FromResult(result);
}
public Query CreateQueryFragment(LuceneQueryContext context, JObject queryObj)
{
var first = queryObj.Properties().First();
Query query = null;
foreach (var queryProvider in _queryProviders)
{
query = queryProvider.CreateQuery(this, context, first.Name, (JObject)first.Value);
if (query != null)
{
break;
}
}
return query;
}
public static List<string> Tokenize(string fieldName, string text, Analyzer analyzer)
{
if (string.IsNullOrEmpty(text))
{
return new List<string>();
}
var result = new List<string>();
using (var tokenStream = analyzer.GetTokenStream(fieldName, text))
{
tokenStream.Reset();
while (tokenStream.IncrementToken())
{
var termAttribute = tokenStream.GetAttribute<ICharTermAttribute>();
if (termAttribute != null)
{
result.Add(termAttribute.ToString());
}
}
}
return result;
}
}
}