diff --git a/app/guide/20210808180117-6v0mkxr/20200923234011-ieuun1p/20210808180303-l3qg72k/20201222100339-i5hzcph.sy b/app/guide/20210808180117-6v0mkxr/20200923234011-ieuun1p/20210808180303-l3qg72k/20201222100339-i5hzcph.sy index 7a79958a6..5ff061f46 100644 --- a/app/guide/20210808180117-6v0mkxr/20200923234011-ieuun1p/20210808180303-l3qg72k/20201222100339-i5hzcph.sy +++ b/app/guide/20210808180117-6v0mkxr/20200923234011-ieuun1p/20210808180303-l3qg72k/20201222100339-i5hzcph.sy @@ -6,7 +6,7 @@ "id": "20201222100339-i5hzcph", "title": "Database table", "type": "doc", - "updated": "20221014133135" + "updated": "20241024010556" }, "Children": [ { @@ -689,7 +689,8 @@ "Type": "NodeHeading", "HeadingLevel": 2, "Properties": { - "id": "20201224120448-dd94dgz" + "id": "20201224120448-dd94dgz", + "updated": "20241024010556" }, "Children": [ { @@ -713,7 +714,7 @@ }, "Properties": { "id": "20210112165011-irm4wch", - "updated": "20220427104543" + "updated": "20241024010556" }, "Children": [ { @@ -792,16 +793,21 @@ }, "Properties": { "id": "20210112165011-n8zrkxm", - "updated": "20220312010003" + "updated": "20241024010556" }, "Children": [ { "ID": "20210210104251-nno6rgh", "Type": "NodeParagraph", "Properties": { - "id": "20210210104251-nno6rgh" + "id": "20210210104251-nno6rgh", + "updated": "20210210104251" }, "Children": [ + { + "Type": "NodeText", + "Data": "​" + }, { "Type": "NodeTextMark", "TextMarkType": "code", @@ -809,7 +815,7 @@ }, { "Type": "NodeText", - "Data": " field" + "Data": "​ field" } ] }, @@ -819,40 +825,9 @@ "ListData": {}, "Properties": { "id": "20210112165011-fodiphq", - "updated": "20220312010003" + "updated": "20241024010556" }, "Children": [ - { - "ID": "20210112165011-hb9w8kd", - "Type": "NodeListItem", - "ListData": { - "BulletChar": 42, - "Marker": "Kg==" - }, - "Properties": { - "id": "20210112165011-hb9w8kd" - }, - "Children": [ - { - "ID": "20210210104251-iy9ugib", - "Type": "NodeParagraph", - "Properties": { - "id": "20210210104251-iy9ugib" - }, - "Children": [ - { - "Type": "NodeText", - "Data": "Document block: " - }, - { - "Type": "NodeTextMark", - "TextMarkType": "code", - "TextMarkTextContent": "0" - } - ] - } - ] - }, { "ID": "20210112165011-epgryib", "Type": "NodeListItem", @@ -861,14 +836,16 @@ "Marker": "Kg==" }, "Properties": { - "id": "20210112165011-epgryib" + "id": "20210112165011-epgryib", + "updated": "20210112165011" }, "Children": [ { "ID": "20210210104251-blu4b7p", "Type": "NodeParagraph", "Properties": { - "id": "20210210104251-blu4b7p" + "id": "20210210104251-blu4b7p", + "updated": "20210210104251" }, "Children": [ { @@ -879,6 +856,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "5" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -912,6 +893,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "10" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -945,6 +930,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "10" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -978,6 +967,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "10" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -1011,6 +1004,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "10" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -1044,6 +1041,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "10" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -1077,6 +1078,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "20" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -1110,6 +1115,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "20" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -1143,6 +1152,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "20" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -1176,6 +1189,84 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "30" + }, + { + "Type": "NodeText", + "Data": "​" + } + ] + } + ] + }, + { + "ID": "20241024001044-dcps4dt", + "Type": "NodeListItem", + "ListData": { + "BulletChar": 42, + "Marker": "Kg==" + }, + "Properties": { + "id": "20241024001044-dcps4dt", + "updated": "20241024001049" + }, + "Children": [ + { + "ID": "20241024001044-99gyvks", + "Type": "NodeParagraph", + "Properties": { + "id": "20241024001044-99gyvks", + "updated": "20241024001049" + }, + "Children": [ + { + "Type": "NodeText", + "Data": "Database block: " + }, + { + "Type": "NodeTextMark", + "TextMarkType": "code", + "TextMarkTextContent": "30" + }, + { + "Type": "NodeText", + "Data": "​" + } + ] + } + ] + }, + { + "ID": "20241024001039-ohxxgjo", + "Type": "NodeListItem", + "ListData": { + "BulletChar": 42, + "Marker": "Kg==" + }, + "Properties": { + "id": "20241024001039-ohxxgjo", + "updated": "20241024010556" + }, + "Children": [ + { + "ID": "20241024001039-pm9zy3x", + "Type": "NodeParagraph", + "Properties": { + "id": "20241024001039-pm9zy3x", + "updated": "20241024010556" + }, + "Children": [ + { + "Type": "NodeText", + "Data": "Document block: " + }, + { + "Type": "NodeTextMark", + "TextMarkType": "code", + "TextMarkTextContent": "0" + }, + { + "Type": "NodeText", + "Data": "​" } ] } diff --git a/app/guide/20210808180117-czj9bvb/20200812220555-lj3enxa/20210808180320-gyngv2x/20201222093044-rx4zjoy.sy b/app/guide/20210808180117-czj9bvb/20200812220555-lj3enxa/20210808180320-gyngv2x/20201222093044-rx4zjoy.sy index 2c4e6828b..82581fc56 100644 --- a/app/guide/20210808180117-czj9bvb/20200812220555-lj3enxa/20210808180320-gyngv2x/20201222093044-rx4zjoy.sy +++ b/app/guide/20210808180117-czj9bvb/20200812220555-lj3enxa/20210808180320-gyngv2x/20201222093044-rx4zjoy.sy @@ -6,7 +6,7 @@ "id": "20201222093044-rx4zjoy", "title": "数据库表", "type": "doc", - "updated": "20221014133123" + "updated": "20241024010538" }, "Children": [ { @@ -689,7 +689,8 @@ "Type": "NodeHeading", "HeadingLevel": 2, "Properties": { - "id": "20201224120447-lezmdb3" + "id": "20201224120447-lezmdb3", + "updated": "20241024010538" }, "Children": [ { @@ -713,7 +714,7 @@ }, "Properties": { "id": "20201224120447-ij3ivd5", - "updated": "20220427104619" + "updated": "20241024010538" }, "Children": [ { @@ -796,16 +797,21 @@ }, "Properties": { "id": "20210112160050-sd8nvwk", - "updated": "20220312005741" + "updated": "20241024010538" }, "Children": [ { "ID": "20210210103236-4q63z1f", "Type": "NodeParagraph", "Properties": { - "id": "20210210103236-4q63z1f" + "id": "20210210103236-4q63z1f", + "updated": "20210210103236" }, "Children": [ + { + "Type": "NodeText", + "Data": "​" + }, { "Type": "NodeTextMark", "TextMarkType": "code", @@ -813,7 +819,7 @@ }, { "Type": "NodeText", - "Data": " 字段" + "Data": "​ 字段" } ] }, @@ -823,40 +829,9 @@ "ListData": {}, "Properties": { "id": "20210112160059-bc0lg2b", - "updated": "20220312005741" + "updated": "20241024010538" }, "Children": [ - { - "ID": "20210112160058-9fxe2cs", - "Type": "NodeListItem", - "ListData": { - "BulletChar": 42, - "Marker": "Kg==" - }, - "Properties": { - "id": "20210112160058-9fxe2cs" - }, - "Children": [ - { - "ID": "20210210103236-i2foidw", - "Type": "NodeParagraph", - "Properties": { - "id": "20210210103236-i2foidw" - }, - "Children": [ - { - "Type": "NodeText", - "Data": "文档块:" - }, - { - "Type": "NodeTextMark", - "TextMarkType": "code", - "TextMarkTextContent": "0" - } - ] - } - ] - }, { "ID": "20210112160120-74nf28j", "Type": "NodeListItem", @@ -865,14 +840,16 @@ "Marker": "Kg==" }, "Properties": { - "id": "20210112160120-74nf28j" + "id": "20210112160120-74nf28j", + "updated": "20210112160120" }, "Children": [ { "ID": "20210210103236-f9jdxfd", "Type": "NodeParagraph", "Properties": { - "id": "20210210103236-f9jdxfd" + "id": "20210210103236-f9jdxfd", + "updated": "20210210103236" }, "Children": [ { @@ -883,6 +860,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "5" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -916,6 +897,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "10" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -949,6 +934,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "10" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -982,6 +971,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "10" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -1015,6 +1008,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "10" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -1048,6 +1045,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "10" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -1081,6 +1082,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "20" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -1114,6 +1119,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "20" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -1147,6 +1156,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "20" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -1180,6 +1193,84 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "30" + }, + { + "Type": "NodeText", + "Data": "​" + } + ] + } + ] + }, + { + "ID": "20241024000912-uo2zwia", + "Type": "NodeListItem", + "ListData": { + "BulletChar": 42, + "Marker": "Kg==" + }, + "Properties": { + "id": "20241024000912-uo2zwia", + "updated": "20241024000912" + }, + "Children": [ + { + "ID": "20241024000912-xai3l1p", + "Type": "NodeParagraph", + "Properties": { + "id": "20241024000912-xai3l1p", + "updated": "20241024000917" + }, + "Children": [ + { + "Type": "NodeText", + "Data": "数据库块:" + }, + { + "Type": "NodeTextMark", + "TextMarkType": "code", + "TextMarkTextContent": "30" + }, + { + "Type": "NodeText", + "Data": "​" + } + ] + } + ] + }, + { + "ID": "20241024000917-3vhxi15", + "Type": "NodeListItem", + "ListData": { + "BulletChar": 42, + "Marker": "Kg==" + }, + "Properties": { + "id": "20241024000917-3vhxi15", + "updated": "20241024010538" + }, + "Children": [ + { + "ID": "20241024000917-xs7tchv", + "Type": "NodeParagraph", + "Properties": { + "id": "20241024000917-xs7tchv", + "updated": "20241024010538" + }, + "Children": [ + { + "Type": "NodeText", + "Data": "文档块:" + }, + { + "Type": "NodeTextMark", + "TextMarkType": "code", + "TextMarkTextContent": "0" + }, + { + "Type": "NodeText", + "Data": "​" } ] } diff --git a/app/guide/20211226090932-5lcq56f/20211226115423-d5z1joq/20211226120933-vnjgwwh/20211226121808-fnxmngk.sy b/app/guide/20211226090932-5lcq56f/20211226115423-d5z1joq/20211226120933-vnjgwwh/20211226121808-fnxmngk.sy index 0c4643cfc..f1944b4d1 100644 --- a/app/guide/20211226090932-5lcq56f/20211226115423-d5z1joq/20211226120933-vnjgwwh/20211226121808-fnxmngk.sy +++ b/app/guide/20211226090932-5lcq56f/20211226115423-d5z1joq/20211226120933-vnjgwwh/20211226121808-fnxmngk.sy @@ -5,7 +5,8 @@ "Properties": { "id": "20211226121808-fnxmngk", "title": "資料庫表", - "updated": "20230630110035" + "type": "doc", + "updated": "20241024010548" }, "Children": [ { @@ -686,7 +687,7 @@ "HeadingLevel": 2, "Properties": { "id": "20211226121831-zvnhouv", - "updated": "20211228132848" + "updated": "20241024010548" }, "Children": [ { @@ -701,7 +702,7 @@ "ListData": {}, "Properties": { "id": "20211226121831-oj726eb", - "updated": "20230630110035" + "updated": "20241024010548" }, "Children": [ { @@ -777,7 +778,7 @@ }, "Properties": { "id": "20211226121831-zs0ji69", - "updated": "20220312005849" + "updated": "20241024010548" }, "Children": [ { @@ -788,6 +789,10 @@ "updated": "20211228134348" }, "Children": [ + { + "Type": "NodeText", + "Data": "​" + }, { "Type": "NodeTextMark", "TextMarkType": "code", @@ -795,7 +800,7 @@ }, { "Type": "NodeText", - "Data": " 欄位" + "Data": "​ 欄位" } ] }, @@ -805,40 +810,9 @@ "ListData": {}, "Properties": { "id": "20211226121831-6ak7dij", - "updated": "20220312005849" + "updated": "20241024010548" }, "Children": [ - { - "ID": "20211226121831-0ko7h04", - "Type": "NodeListItem", - "ListData": { - "BulletChar": 42, - "Marker": "Kg==" - }, - "Properties": { - "id": "20211226121831-0ko7h04" - }, - "Children": [ - { - "ID": "20211226121831-twcl260", - "Type": "NodeParagraph", - "Properties": { - "id": "20211226121831-twcl260" - }, - "Children": [ - { - "Type": "NodeText", - "Data": "文檔塊:" - }, - { - "Type": "NodeTextMark", - "TextMarkType": "code", - "TextMarkTextContent": "0" - } - ] - } - ] - }, { "ID": "20211226121831-vs8zc2q", "Type": "NodeListItem", @@ -847,14 +821,16 @@ "Marker": "Kg==" }, "Properties": { - "id": "20211226121831-vs8zc2q" + "id": "20211226121831-vs8zc2q", + "updated": "20211226121831" }, "Children": [ { "ID": "20211226121831-f2bpy1c", "Type": "NodeParagraph", "Properties": { - "id": "20211226121831-f2bpy1c" + "id": "20211226121831-f2bpy1c", + "updated": "20211226121831" }, "Children": [ { @@ -865,6 +841,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "5" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -898,6 +878,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "10" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -931,6 +915,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "10" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -964,6 +952,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "10" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -997,6 +989,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "10" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -1030,6 +1026,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "10" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -1063,6 +1063,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "20" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -1096,6 +1100,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "20" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -1129,6 +1137,10 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "20" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -1162,6 +1174,84 @@ "Type": "NodeTextMark", "TextMarkType": "code", "TextMarkTextContent": "30" + }, + { + "Type": "NodeText", + "Data": "​" + } + ] + } + ] + }, + { + "ID": "20241024001004-ua7jo68", + "Type": "NodeListItem", + "ListData": { + "BulletChar": 42, + "Marker": "Kg==" + }, + "Properties": { + "id": "20241024001004-ua7jo68", + "updated": "20241024001004" + }, + "Children": [ + { + "ID": "20241024001004-wu134y6", + "Type": "NodeParagraph", + "Properties": { + "id": "20241024001004-wu134y6", + "updated": "20241024001020" + }, + "Children": [ + { + "Type": "NodeText", + "Data": "資料庫塊:" + }, + { + "Type": "NodeTextMark", + "TextMarkType": "code", + "TextMarkTextContent": "30" + }, + { + "Type": "NodeText", + "Data": "​" + } + ] + } + ] + }, + { + "ID": "20241024001004-awor1zs", + "Type": "NodeListItem", + "ListData": { + "BulletChar": 42, + "Marker": "Kg==" + }, + "Properties": { + "id": "20241024001004-awor1zs", + "updated": "20241024010548" + }, + "Children": [ + { + "ID": "20241024001004-wtbxwea", + "Type": "NodeParagraph", + "Properties": { + "id": "20241024001004-wtbxwea", + "updated": "20241024010548" + }, + "Children": [ + { + "Type": "NodeText", + "Data": "文檔塊:" + }, + { + "Type": "NodeTextMark", + "TextMarkType": "code", + "TextMarkTextContent": "0" + }, + { + "Type": "NodeText", + "Data": "​" } ] } @@ -1170,6 +1260,28 @@ ] } ] + }, + { + "ID": "20241024000958-wx7ry0w", + "Type": "NodeListItem", + "ListData": { + "BulletChar": 42, + "Marker": "Kg==" + }, + "Properties": { + "id": "20241024000958-wx7ry0w", + "updated": "20241024000958" + }, + "Children": [ + { + "ID": "20241024000958-9qbls2u", + "Type": "NodeParagraph", + "Properties": { + "id": "20241024000958-9qbls2u", + "updated": "20241024000958" + } + } + ] } ] } diff --git a/app/guide/20240530133126-axarxgx/20240530101000-4qitucx/20240530101000-a91lmk2/20240530101000-58z6rjh.sy b/app/guide/20240530133126-axarxgx/20240530101000-4qitucx/20240530101000-a91lmk2/20240530101000-58z6rjh.sy index b2e4a48b2..14b1c9b6d 100644 --- a/app/guide/20240530133126-axarxgx/20240530101000-4qitucx/20240530101000-a91lmk2/20240530101000-58z6rjh.sy +++ b/app/guide/20240530133126-axarxgx/20240530101000-4qitucx/20240530101000-a91lmk2/20240530101000-58z6rjh.sy @@ -7,7 +7,7 @@ "id": "20240530101000-58z6rjh", "title": "データベーステーブル", "type": "doc", - "updated": "20240530101000" + "updated": "20241024010606" }, "Children": [ { @@ -704,7 +704,7 @@ "Properties": { "ID": "20240530101000-hotqrms", "id": "20240530101000-214gvio", - "updated": "20240530101000" + "updated": "20241024010606" }, "Children": [ { @@ -725,7 +725,7 @@ "Properties": { "ID": "20240530101000-e9bmqha", "id": "20240530101000-4hc7zl9", - "updated": "20240530101000" + "updated": "20241024010606" }, "Children": [ { @@ -811,14 +811,13 @@ "Properties": { "ID": "20240530101000-rsk9w3i", "id": "20240530101000-7pu1enh", - "updated": "20240530101000" + "updated": "20241024010606" }, "Children": [ { "ID": "20240530101000-mne3cfq", "Type": "NodeParagraph", "Properties": { - "ID": "20240530101000-zat4xji", "id": "20240530101000-mne3cfq", "updated": "20240530101000" }, @@ -843,49 +842,10 @@ "Type": "NodeList", "ListData": {}, "Properties": { - "ID": "20240530101000-2cxguwt", "id": "20240530101000-8rv3wzu", - "updated": "20240530101000" + "updated": "20241024010606" }, "Children": [ - { - "ID": "20240530101000-gholggk", - "Type": "NodeListItem", - "ListData": { - "BulletChar": 42, - "Marker": "Kg==" - }, - "Properties": { - "ID": "20240530101000-13st18e", - "id": "20240530101000-gholggk" - }, - "Children": [ - { - "ID": "20240530101000-6bl43rm", - "Type": "NodeParagraph", - "Properties": { - "ID": "20240530101000-mjdpqnn", - "id": "20240530101000-6bl43rm", - "updated": "20240530101000" - }, - "Children": [ - { - "Type": "NodeText", - "Data": "ドキュメントブロック: " - }, - { - "Type": "NodeTextMark", - "TextMarkType": "code", - "TextMarkTextContent": "0" - }, - { - "Type": "NodeText", - "Data": "​" - } - ] - } - ] - }, { "ID": "20240530101000-bbi6u3a", "Type": "NodeListItem", @@ -894,15 +854,14 @@ "Marker": "Kg==" }, "Properties": { - "ID": "20240530101000-73yi5ls", - "id": "20240530101000-bbi6u3a" + "id": "20240530101000-bbi6u3a", + "updated": "20240530101000" }, "Children": [ { "ID": "20240530101000-hazo7qh", "Type": "NodeParagraph", "Properties": { - "ID": "20240530101000-6tc0as0", "id": "20240530101000-hazo7qh", "updated": "20240530101000" }, @@ -932,7 +891,6 @@ "Marker": "Kg==" }, "Properties": { - "ID": "20240530101000-jjy3ouk", "id": "20240530101000-vmb7t9y", "updated": "20240530101000" }, @@ -941,7 +899,6 @@ "ID": "20240530101000-crv9hv9", "Type": "NodeParagraph", "Properties": { - "ID": "20240530101000-mr7pw7r", "id": "20240530101000-crv9hv9", "updated": "20240530101000" }, @@ -971,7 +928,6 @@ "Marker": "Kg==" }, "Properties": { - "ID": "20240530101000-cyc3wg7", "id": "20240530101000-8u5e3kt", "updated": "20240530101000" }, @@ -980,7 +936,6 @@ "ID": "20240530101000-o40x5nb", "Type": "NodeParagraph", "Properties": { - "ID": "20240530101000-pvgr1e1", "id": "20240530101000-o40x5nb", "updated": "20240530101000" }, @@ -1010,7 +965,6 @@ "Marker": "Kg==" }, "Properties": { - "ID": "20240530101000-iuogeyw", "id": "20240530101000-m24vrgz", "updated": "20240530101000" }, @@ -1019,7 +973,6 @@ "ID": "20240530101000-siukphp", "Type": "NodeParagraph", "Properties": { - "ID": "20240530101000-0ewvks9", "id": "20240530101000-siukphp", "updated": "20240530101000" }, @@ -1049,7 +1002,6 @@ "Marker": "Kg==" }, "Properties": { - "ID": "20240530101000-l6xju21", "id": "20240530101000-v2gkqj8", "updated": "20240530101000" }, @@ -1058,7 +1010,6 @@ "ID": "20240530101000-t7mgtfk", "Type": "NodeParagraph", "Properties": { - "ID": "20240530101000-8s1lmsc", "id": "20240530101000-t7mgtfk", "updated": "20240530101000" }, @@ -1088,7 +1039,6 @@ "Marker": "Kg==" }, "Properties": { - "ID": "20240530101000-n58qmno", "id": "20240530101000-94lacat", "updated": "20240530101000" }, @@ -1097,7 +1047,6 @@ "ID": "20240530101000-o40rn1y", "Type": "NodeParagraph", "Properties": { - "ID": "20240530101000-6zfuf1k", "id": "20240530101000-o40rn1y", "updated": "20240530101000" }, @@ -1127,7 +1076,6 @@ "Marker": "Kg==" }, "Properties": { - "ID": "20240530101000-9fnnx0z", "id": "20240530101000-vad5ds7", "updated": "20240530101000" }, @@ -1136,7 +1084,6 @@ "ID": "20240530101000-fszxybt", "Type": "NodeParagraph", "Properties": { - "ID": "20240530101000-ud5qscz", "id": "20240530101000-fszxybt", "updated": "20240530101000" }, @@ -1166,7 +1113,6 @@ "Marker": "Kg==" }, "Properties": { - "ID": "20240530101000-vsf16ms", "id": "20240530101000-bg5woa1", "updated": "20240530101000" }, @@ -1175,7 +1121,6 @@ "ID": "20240530101000-vz5x0vh", "Type": "NodeParagraph", "Properties": { - "ID": "20240530101000-pdokiyu", "id": "20240530101000-vz5x0vh", "updated": "20240530101000" }, @@ -1205,7 +1150,6 @@ "Marker": "Kg==" }, "Properties": { - "ID": "20240530101000-cue1u5r", "id": "20240530101000-szwjkk8", "updated": "20240530101000" }, @@ -1214,7 +1158,6 @@ "ID": "20240530101000-hrexfa7", "Type": "NodeParagraph", "Properties": { - "ID": "20240530101000-mxkgtk1", "id": "20240530101000-hrexfa7", "updated": "20240530101000" }, @@ -1244,7 +1187,6 @@ "Marker": "Kg==" }, "Properties": { - "ID": "20240530101000-r4vi4kx", "id": "20240530101000-n8p7p53", "updated": "20240530101000" }, @@ -1253,7 +1195,6 @@ "ID": "20240530101000-d1jth4r", "Type": "NodeParagraph", "Properties": { - "ID": "20240530101000-4jp6zai", "id": "20240530101000-d1jth4r", "updated": "20240530101000" }, @@ -1274,6 +1215,80 @@ ] } ] + }, + { + "ID": "20241024001112-d1aen8d", + "Type": "NodeListItem", + "ListData": { + "BulletChar": 42, + "Marker": "Kg==" + }, + "Properties": { + "id": "20241024001112-d1aen8d", + "updated": "20241024001112" + }, + "Children": [ + { + "ID": "20241024001112-xvg1o5n", + "Type": "NodeParagraph", + "Properties": { + "id": "20241024001112-xvg1o5n", + "updated": "20241024001114" + }, + "Children": [ + { + "Type": "NodeText", + "Data": "データベースブロック: " + }, + { + "Type": "NodeTextMark", + "TextMarkType": "code", + "TextMarkTextContent": "30" + }, + { + "Type": "NodeText", + "Data": "​" + } + ] + } + ] + }, + { + "ID": "20241024001115-q3v9s9k", + "Type": "NodeListItem", + "ListData": { + "BulletChar": 42, + "Marker": "Kg==" + }, + "Properties": { + "id": "20241024001115-q3v9s9k", + "updated": "20241024010606" + }, + "Children": [ + { + "ID": "20241024001115-xn6pni8", + "Type": "NodeParagraph", + "Properties": { + "id": "20241024001115-xn6pni8", + "updated": "20241024010606" + }, + "Children": [ + { + "Type": "NodeText", + "Data": "ドキュメントブロック: " + }, + { + "Type": "NodeTextMark", + "TextMarkType": "code", + "TextMarkTextContent": "0" + }, + { + "Type": "NodeText", + "Data": "​" + } + ] + } + ] } ] } diff --git a/kernel/model/search.go b/kernel/model/search.go index 751051193..ef4be5674 100644 --- a/kernel/model/search.go +++ b/kernel/model/search.go @@ -914,27 +914,38 @@ func FullTextSearchBlock(query string, boxes, paths []string, types map[string]b query = trimQuery } + var ignoreFilter string + if ignoreLines := getSearchIgnoreLines(); 0 < len(ignoreLines) { + // Support ignore search results https://github.com/siyuan-note/siyuan/issues/10089 + buf := bytes.Buffer{} + for _, line := range ignoreLines { + buf.WriteString(" AND ") + buf.WriteString(line) + } + ignoreFilter += buf.String() + } + beforeLen := 36 var blocks []*Block orderByClause := buildOrderBy(query, method, orderBy) switch method { case 1: // 查询语法 - filter := buildTypeFilter(types) + typeFilter := buildTypeFilter(types) boxFilter := buildBoxesFilter(boxes) pathFilter := buildPathsFilter(paths) - blocks, matchedBlockCount, matchedRootCount = fullTextSearchByQuerySyntax(query, boxFilter, pathFilter, filter, orderByClause, beforeLen, page, pageSize) + blocks, matchedBlockCount, matchedRootCount = fullTextSearchByQuerySyntax(query, boxFilter, pathFilter, typeFilter, ignoreFilter, orderByClause, beforeLen, page, pageSize) case 2: // SQL blocks, matchedBlockCount, matchedRootCount = searchBySQL(query, beforeLen, page, pageSize) case 3: // 正则表达式 typeFilter := buildTypeFilter(types) boxFilter := buildBoxesFilter(boxes) pathFilter := buildPathsFilter(paths) - blocks, matchedBlockCount, matchedRootCount = fullTextSearchByRegexp(query, boxFilter, pathFilter, typeFilter, orderByClause, beforeLen, page, pageSize) + blocks, matchedBlockCount, matchedRootCount = fullTextSearchByRegexp(query, boxFilter, pathFilter, typeFilter, ignoreFilter, orderByClause, beforeLen, page, pageSize) default: // 关键字 - filter := buildTypeFilter(types) + typeFilter := buildTypeFilter(types) boxFilter := buildBoxesFilter(boxes) pathFilter := buildPathsFilter(paths) - blocks, matchedBlockCount, matchedRootCount = fullTextSearchByKeyword(query, boxFilter, pathFilter, filter, orderByClause, beforeLen, page, pageSize) + blocks, matchedBlockCount, matchedRootCount = fullTextSearchByKeyword(query, boxFilter, pathFilter, typeFilter, ignoreFilter, orderByClause, beforeLen, page, pageSize) } pageCount = (matchedBlockCount + pageSize - 1) / pageSize @@ -1264,32 +1275,30 @@ func extractID(content string) (ret string) { return } -func fullTextSearchByQuerySyntax(query, boxFilter, pathFilter, typeFilter, orderBy string, beforeLen, page, pageSize int) (ret []*Block, matchedBlockCount, matchedRootCount int) { +func fullTextSearchByQuerySyntax(query, boxFilter, pathFilter, typeFilter, ignoreFilter, orderBy string, beforeLen, page, pageSize int) (ret []*Block, matchedBlockCount, matchedRootCount int) { query = filterQueryInvisibleChars(query) if ast.IsNodeIDPattern(query) { ret, matchedBlockCount, matchedRootCount = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+query+"'", beforeLen, page, pageSize) return } - return fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, orderBy, beforeLen, page, pageSize) + return fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, ignoreFilter, orderBy, beforeLen, page, pageSize) } -func fullTextSearchByKeyword(query, boxFilter, pathFilter, typeFilter string, orderBy string, beforeLen, page, pageSize int) (ret []*Block, matchedBlockCount, matchedRootCount int) { +func fullTextSearchByKeyword(query, boxFilter, pathFilter, typeFilter, ignoreFilter string, orderBy string, beforeLen, page, pageSize int) (ret []*Block, matchedBlockCount, matchedRootCount int) { query = filterQueryInvisibleChars(query) if ast.IsNodeIDPattern(query) { ret, matchedBlockCount, matchedRootCount = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+query+"'", beforeLen, page, pageSize) return } - query = stringQuery(query) - return fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, orderBy, beforeLen, page, pageSize) + return fullTextSearchByFTSWithRoot(query, boxFilter, pathFilter, typeFilter, ignoreFilter, orderBy, beforeLen, page, pageSize) } -func fullTextSearchByRegexp(exp, boxFilter, pathFilter, typeFilter, orderBy string, beforeLen, page, pageSize int) (ret []*Block, matchedBlockCount, matchedRootCount int) { +func fullTextSearchByRegexp(exp, boxFilter, pathFilter, typeFilter, ignoreFilter, orderBy string, beforeLen, page, pageSize int) (ret []*Block, matchedBlockCount, matchedRootCount int) { exp = filterQueryInvisibleChars(exp) fieldFilter := fieldRegexp(exp) stmt := "SELECT * FROM `blocks` WHERE " + fieldFilter + " AND type IN " + typeFilter - stmt += boxFilter + pathFilter - stmt += " " + orderBy + stmt += boxFilter + pathFilter + ignoreFilter + " " + orderBy regex := regexp.MustCompile(exp) blocks := sql.SelectBlocksRegex(stmt, regex, Conf.Search.Name, Conf.Search.Alias, Conf.Search.Memo, Conf.Search.IAL, page, pageSize) ret = fromSQLBlocks(&blocks, "", beforeLen) @@ -1297,13 +1306,13 @@ func fullTextSearchByRegexp(exp, boxFilter, pathFilter, typeFilter, orderBy stri ret = []*Block{} } - matchedBlockCount, matchedRootCount = fullTextSearchCountByRegexp(exp, boxFilter, pathFilter, typeFilter) + matchedBlockCount, matchedRootCount = fullTextSearchCountByRegexp(exp, boxFilter, pathFilter, typeFilter, ignoreFilter) return } -func fullTextSearchCountByRegexp(exp, boxFilter, pathFilter, typeFilter string) (matchedBlockCount, matchedRootCount int) { +func fullTextSearchCountByRegexp(exp, boxFilter, pathFilter, typeFilter, ignoreFilter string) (matchedBlockCount, matchedRootCount int) { fieldFilter := fieldRegexp(exp) - stmt := "SELECT COUNT(id) AS `matches`, COUNT(DISTINCT(root_id)) AS `docs` FROM `blocks` WHERE " + fieldFilter + " AND type IN " + typeFilter + stmt := "SELECT COUNT(id) AS `matches`, COUNT(DISTINCT(root_id)) AS `docs` FROM `blocks` WHERE " + fieldFilter + " AND type IN " + typeFilter + ignoreFilter stmt += boxFilter + pathFilter result, _ := sql.QueryNoLimit(stmt) if 1 > len(result) { @@ -1314,7 +1323,8 @@ func fullTextSearchCountByRegexp(exp, boxFilter, pathFilter, typeFilter string) return } -func fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, orderBy string, beforeLen, page, pageSize int) (ret []*Block, matchedBlockCount, matchedRootCount int) { +func fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, ignoreFilter, orderBy string, beforeLen, page, pageSize int) (ret []*Block, matchedBlockCount, matchedRootCount int) { + query = stringQuery(query) table := "blocks_fts" // 大小写敏感 if !Conf.Search.CaseSensitive { table = "blocks_fts_case_insensitive" @@ -1330,19 +1340,7 @@ func fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, orderBy strin "fcontent, markdown, length, type, subtype, ial, sort, created, updated" stmt := "SELECT " + projections + " FROM " + table + " WHERE (`" + table + "` MATCH '" + columnFilter() + ":(" + query + ")'" stmt += ") AND type IN " + typeFilter - stmt += boxFilter + pathFilter - - if ignoreLines := getSearchIgnoreLines(); 0 < len(ignoreLines) { - // Support ignore search results https://github.com/siyuan-note/siyuan/issues/10089 - buf := bytes.Buffer{} - for _, line := range ignoreLines { - buf.WriteString(" AND ") - buf.WriteString(line) - } - stmt += buf.String() - } - - stmt += " " + orderBy + stmt += boxFilter + pathFilter + ignoreFilter + " " + orderBy stmt += " LIMIT " + strconv.Itoa(pageSize) + " OFFSET " + strconv.Itoa((page-1)*pageSize) blocks := sql.SelectBlocksRawStmt(stmt, page, pageSize) ret = fromSQLBlocks(&blocks, "", beforeLen) @@ -1350,7 +1348,108 @@ func fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, orderBy strin ret = []*Block{} } - matchedBlockCount, matchedRootCount = fullTextSearchCount(query, boxFilter, pathFilter, typeFilter) + matchedBlockCount, matchedRootCount = fullTextSearchCountByFTS(query, boxFilter, pathFilter, typeFilter, ignoreFilter) + return +} + +func fullTextSearchCountByFTS(query, boxFilter, pathFilter, typeFilter, ignoreFilter string) (matchedBlockCount, matchedRootCount int) { + if ast.IsNodeIDPattern(query) { + ret, _ := sql.QueryNoLimit("SELECT COUNT(id) AS `matches`, COUNT(DISTINCT(root_id)) AS `docs` FROM `blocks` WHERE `id` = '" + query + "'") + if 1 > len(ret) { + return + } + matchedBlockCount = int(ret[0]["matches"].(int64)) + matchedRootCount = int(ret[0]["docs"].(int64)) + return + } + + table := "blocks_fts" // 大小写敏感 + if !Conf.Search.CaseSensitive { + table = "blocks_fts_case_insensitive" + } + + stmt := "SELECT COUNT(id) AS `matches`, COUNT(DISTINCT(root_id)) AS `docs` FROM `" + table + "` WHERE (`" + table + "` MATCH '" + columnFilter() + ":(" + query + ")'" + stmt += ") AND type IN " + typeFilter + stmt += boxFilter + pathFilter + ignoreFilter + result, _ := sql.QueryNoLimit(stmt) + if 1 > len(result) { + return + } + matchedBlockCount = int(result[0]["matches"].(int64)) + matchedRootCount = int(result[0]["docs"].(int64)) + return +} + +func fullTextSearchByFTSWithRoot(query, boxFilter, pathFilter, typeFilter, ignoreFilter, orderBy string, beforeLen, page, pageSize int) (ret []*Block, matchedBlockCount, matchedRootCount int) { + table := "blocks_fts" // 大小写敏感 + if !Conf.Search.CaseSensitive { + table = "blocks_fts_case_insensitive" + } + + mQ := stringQuery(query) + bMatchStmt := "SELECT id FROM " + table + " WHERE (" + table + " MATCH '" + columnFilter() + ":(" + mQ + ")')" + bMatchStmt += " AND type IN " + typeFilter + boxFilter + pathFilter + ignoreFilter + + query = strings.ReplaceAll(query, "'", "''") + query = strings.ReplaceAll(query, "\"", "\"\"") + keywords := strings.Split(query, " ") + var likeFilter string + for i, keyword := range keywords { + likeFilter += "docContent LIKE '%" + keyword + "%'" + if i < len(keywords)-1 { + likeFilter += " AND " + } + } + dMatchStmt := "SELECT root_id, GROUP_CONCAT(content) AS docContent" + + " FROM " + table + " WHERE type IN " + typeFilter + boxFilter + pathFilter + ignoreFilter + + " GROUP BY root_id HAVING " + likeFilter + cteStmt := "WITH docs AS (" + dMatchStmt + "), blocks AS (" + bMatchStmt + ")" + cteStmt += "\nSELECT * FROM " + table + " WHERE id IN (SELECT id FROM blocks) OR id IN (SELECT root_id FROM docs)" + countStmt := cteStmt + cteStmt += orderBy + " LIMIT " + strconv.Itoa(pageSize) + " OFFSET " + strconv.Itoa((page-1)*pageSize) + resultBlocks := sql.SelectBlocksRawStmtNoParse(cteStmt, -1) + + // FTS 高亮 + projections := "id, parent_id, root_id, hash, box, path, " + + // Search result content snippet returns more text https://github.com/siyuan-note/siyuan/issues/10707 + "snippet(" + table + ", 6, '" + search.SearchMarkLeft + "', '" + search.SearchMarkRight + "', '...', 512) AS hpath, " + + "snippet(" + table + ", 7, '" + search.SearchMarkLeft + "', '" + search.SearchMarkRight + "', '...', 512) AS name, " + + "snippet(" + table + ", 8, '" + search.SearchMarkLeft + "', '" + search.SearchMarkRight + "', '...', 512) AS alias, " + + "snippet(" + table + ", 9, '" + search.SearchMarkLeft + "', '" + search.SearchMarkRight + "', '...', 512) AS memo, " + + "snippet(" + table + ", 10, '" + search.SearchMarkLeft + "', '" + search.SearchMarkRight + "', '...', 64) AS tag, " + + "snippet(" + table + ", 11, '" + search.SearchMarkLeft + "', '" + search.SearchMarkRight + "', '...', 512) AS content, " + + "fcontent, markdown, length, type, subtype, ial, sort, created, updated" + stmt := "SELECT " + projections + " FROM " + table + " WHERE (`" + table + "` MATCH '" + columnFilter() + ":(" + query + ")'" + stmt += ") AND type IN " + typeFilter + boxFilter + pathFilter + ignoreFilter + orderBy + " LIMIT " + strconv.Itoa(pageSize) + " OFFSET " + strconv.Itoa((page-1)*pageSize) + blocks := sql.SelectBlocksRawStmt(stmt, page, pageSize) + for i, resultBlock := range resultBlocks { + for j, block := range blocks { + if resultBlock.ID == block.ID { + resultBlocks[i] = block + // 减少 blocks + blocks = append(blocks[:j], blocks[j+1:]...) + break + } + } + } + + ret = fromSQLBlocks(&resultBlocks, "", beforeLen) + if 1 > len(ret) { + ret = []*Block{} + } + + matchedBlockCount, matchedRootCount = fullTextSearchCountByStmt(countStmt) + return +} + +func fullTextSearchCountByStmt(stmt string) (matchedBlockCount, matchedRootCount int) { + stmt = "SELECT COUNT(id) AS `matches`, COUNT(DISTINCT(root_id)) AS `docs` FROM (" + stmt + ")" + result, _ := sql.QueryNoLimit(stmt) + if 1 > len(result) { + return + } + matchedBlockCount = int(result[0]["matches"].(int64)) + matchedRootCount = int(result[0]["docs"].(int64)) return } @@ -1399,46 +1498,6 @@ func highlightByRegexp(query, typeFilter, id string) (ret []string) { return } -func fullTextSearchCount(query, boxFilter, pathFilter, typeFilter string) (matchedBlockCount, matchedRootCount int) { - query = filterQueryInvisibleChars(query) - if ast.IsNodeIDPattern(query) { - ret, _ := sql.QueryNoLimit("SELECT COUNT(id) AS `matches`, COUNT(DISTINCT(root_id)) AS `docs` FROM `blocks` WHERE `id` = '" + query + "'") - if 1 > len(ret) { - return - } - matchedBlockCount = int(ret[0]["matches"].(int64)) - matchedRootCount = int(ret[0]["docs"].(int64)) - return - } - - table := "blocks_fts" // 大小写敏感 - if !Conf.Search.CaseSensitive { - table = "blocks_fts_case_insensitive" - } - - stmt := "SELECT COUNT(id) AS `matches`, COUNT(DISTINCT(root_id)) AS `docs` FROM `" + table + "` WHERE (`" + table + "` MATCH '" + columnFilter() + ":(" + query + ")'" - stmt += ") AND type IN " + typeFilter - stmt += boxFilter + pathFilter - - if ignoreLines := getSearchIgnoreLines(); 0 < len(ignoreLines) { - // Support ignore search results https://github.com/siyuan-note/siyuan/issues/10089 - buf := bytes.Buffer{} - for _, line := range ignoreLines { - buf.WriteString(" AND ") - buf.WriteString(line) - } - stmt += buf.String() - } - - result, _ := sql.QueryNoLimit(stmt) - if 1 > len(result) { - return - } - matchedBlockCount = int(result[0]["matches"].(int64)) - matchedRootCount = int(result[0]["docs"].(int64)) - return -} - func markSearch(text string, keyword string, beforeLen int) (marked string, score float64) { if 0 == len(keyword) { marked = text diff --git a/kernel/sql/database.go b/kernel/sql/database.go index 4e8ab20b1..e35008e66 100644 --- a/kernel/sql/database.go +++ b/kernel/sql/database.go @@ -1422,8 +1422,6 @@ func execStmtTx(tx *sql.Tx, stmt string, args ...interface{}) (err error) { func nSort(n *ast.Node) int { switch n.Type { // 以下为块级元素 - case ast.NodeDocument: - return 0 case ast.NodeHeading: return 5 case ast.NodeParagraph: @@ -1446,6 +1444,8 @@ func nSort(n *ast.Node) int { return 30 case ast.NodeAttributeView: return 30 + case ast.NodeDocument: + return 0 case ast.NodeText, ast.NodeTextMark: if n.IsTextMarkType("tag") { return 205